diff --git a/Utilities/ITK/Utilities/DICOMParser/CMakeLists.txt b/Utilities/ITK/Utilities/DICOMParser/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8e3cdb107e578096c2464ddd6ab31eb9b9f0095b
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/CMakeLists.txt
@@ -0,0 +1,62 @@
+# The DICOMParser Library is intended to be included in other
+# projects.  The library's namespace and library name can be
+# configured.
+
+# Typical usage is to import the DICOMParser directory tree into a
+# subdirectory under a parent project and enable the library be used.
+# The CMake listfile above this one configures the library as follows:
+# 
+#  SET(DICOMPARSER_NAMESPACE foodicomparser)
+#  SET(DICOMPARSER_LIBRARY   foodicomparser)
+#  SUBDIRS(DICOMParser)
+#
+
+#-----------------------------------------------------------------------------
+# If a namespace is not specified, use "dicomparser". This should be
+# the case only when dicom is not included inside another project
+#
+IF(NOT DICOMPARSER_NAMESPACE)
+   SET(DICOMPARSER_NAMESPACE dicomparser) 
+   SET(DICOMPARSER_LIBRARY dicomparser)
+   SET(DICOMPARSER_STANDALONE 1)
+ENDIF(NOT DICOMPARSER_NAMESPACE)
+
+
+#-----------------------------------------------------------------------------
+# The project name is that of the specified namespace.
+PROJECT(${DICOMPARSER_NAMESPACE})
+
+# Put the binary tree first in the include path to protect against
+# when people accidently configure in their source tree
+INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})
+
+IF(WIN32)
+  IF(BUILD_SHARED_LIBS)
+    SET(DICOM_DLL 1)
+  ELSE(BUILD_SHARED_LIBS)
+    SET(DICOM_STATIC 1)
+  ENDIF(BUILD_SHARED_LIBS)
+ENDIF(WIN32)
+
+IF(ITK_SOURCE_DIR)
+   # Inside ITK, use its setting.
+   SET(DICOM_ANSI_STDLIB 1)
+ELSE(ITK_SOURCE_DIR)
+   # Not inside ITK, use ANSI streams.
+   SET(DICOM_ANSI_STDLIB 1)
+ENDIF(ITK_SOURCE_DIR)
+
+INCLUDE(${CMAKE_ROOT}/Modules/TestForSTDNamespace.cmake)
+SET(DICOM_NO_STD_NAMESPACE ${CMAKE_NO_STD_NAMESPACE})
+
+
+CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/DICOMCMakeConfig.h.in
+               ${PROJECT_BINARY_DIR}/DICOMCMakeConfig.h)
+
+ADD_LIBRARY(${DICOMPARSER_LIBRARY} DICOMSource.cxx DICOMBuffer.cxx DICOMFile.cxx DICOMParser.cxx DICOMAppHelper.cxx)
+
+INSTALL_TARGETS(/lib/InsightToolkit ${DICOMPARSER_LIBRARY})
+INSTALL_FILES(/include/InsightToolkit "(\\.h|\\.txx)$")
+INSTALL_FILES(/include/InsightToolkit FILES
+  ${PROJECT_BINARY_DIR}/DICOMCMakeConfig.h)
diff --git a/Utilities/ITK/Utilities/DICOMParser/Copyright.txt b/Utilities/ITK/Utilities/DICOMParser/Copyright.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8499456e49ad238040405a9f9ae0b42e9b4c544a
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/Copyright.txt
@@ -0,0 +1,41 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: Copyright.txt,v $
+  Language:  C++
+  Date:      $Date: 2003/10/23 17:42:13 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 2003 Matt Turek
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+ * The name of Matt Turek nor the names of any contributors may be used to 
+   endorse or promote products derived from this software without specific 
+   prior written permission.
+
+ * Modified source versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+=========================================================================*/
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMAppHelper.cxx b/Utilities/ITK/Utilities/DICOMParser/DICOMAppHelper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1091865b9e64a1bf388a2aebf15eef3abc263cbf
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMAppHelper.cxx
@@ -0,0 +1,2446 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMAppHelper.cxx,v $
+  Language:  C++
+  Date:      $Date: 2005/03/15 17:00:37 $
+  Version:   $Revision: 1.72 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( disable : 4786 )
+#pragma warning ( disable : 4503 )
+#pragma warning ( disable : 4710 )
+#pragma warning ( disable : 4702 )
+#pragma warning ( push, 3 )
+#endif 
+
+#include "DICOMConfig.h"
+#include "DICOMAppHelper.h"
+#include "DICOMCallback.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string>
+#include <math.h>
+#include <algorithm>
+
+namespace DICOMPARSER_NAMESPACE
+{
+//#define DEBUG_DICOM_APP_HELPER
+
+class DICOMAppHelperImplementation
+{
+public:
+  // map from series UID to vector of instance UIDs in the series
+  typedef dicom_stl::map<dicom_stl::string, dicom_stl::vector<dicom_stl::string>, ltstdstr> SeriesUIDToInstanceUIDMapType;
+  SeriesUIDToInstanceUIDMapType SeriesUIDToInstanceUIDMap;
+
+  // map from a series Description to an instance UID 
+  typedef dicom_stl::map<dicom_stl::string, dicom_stl::string, ltstdstr> SeriesUIDToSeriesDescriptionMapType;
+  SeriesUIDToSeriesDescriptionMapType SeriesUIDToSeriesDescriptionMap;
+
+  // map from a series body part to an instance UID 
+  typedef dicom_stl::map<dicom_stl::string, dicom_stl::string, ltstdstr> SeriesUIDToBodyPartMapType;
+  SeriesUIDToBodyPartMapType  SeriesUIDToBodyPartMap;
+
+  // map from a series scan option to an instance UID 
+  typedef dicom_stl::map<dicom_stl::string, dicom_stl::string, ltstdstr> SeriesUIDToScanOptionsMapType;
+  SeriesUIDToScanOptionsMapType  SeriesUIDToScanOptionsMap;
+
+  // map from an instance UID to a series UID
+  typedef dicom_stl::map<dicom_stl::string, dicom_stl::string, ltstdstr> InstanceUIDToSeriesUIDMapType;
+  InstanceUIDToSeriesUIDMapType InstanceUIDToSeriesUIDMap;
+
+  // map from an instance UID to a filename
+  typedef dicom_stl::map<dicom_stl::string, dicom_stl::string, ltstdstr> InstanceUIDToFileNameMapType;
+  InstanceUIDToFileNameMapType InstanceUIDToFileNameMap;
+  
+  // map from instance UID to intraseries sortable tags
+  typedef dicom_stl::map<dicom_stl::string, DICOMOrderingElements, ltstdstr> InstanceUIDToSliceOrderingMapType;
+  InstanceUIDToSliceOrderingMapType InstanceUIDToSliceOrderingMap;
+
+  // map for (group, element) to tag info
+  typedef dicom_stl::map<dicom_stl::pair<doublebyte, doublebyte>, DICOMTagInfo> TagMapType;
+  TagMapType TagMap;
+
+  // data structure for a contour (store points as x,y,z,x,y,z,...)
+  // Do we want to have different contour types? POINT, OPEN_PLANAR, CLOSED_PLANAR
+  typedef dicom_stl::vector<float> ContourType;
+
+  // vector of contours
+  typedef dicom_stl::vector<ContourType> ContoursVectorType;
+
+  // map from series UID to vector of contours in that series
+  typedef dicom_stl::map<dicom_stl::string, ContoursVectorType, ltstdstr> SeriesUIDToContoursMapType;
+  SeriesUIDToContoursMapType SeriesUIDToContoursMap;
+
+  // vector of instance UIDs
+  typedef dicom_stl::vector<dicom_stl::string> InstanceUIDVectorType;
+  
+  // map from series UID to referenced instance uid
+  typedef dicom_stl::map<dicom_stl::string, InstanceUIDVectorType, ltstdstr> SeriesUIDToReferencedInstanceUIDMapType;
+  SeriesUIDToReferencedInstanceUIDMapType SeriesUIDToReferencedInstanceUIDMap;
+};
+
+
+struct lt_pair_int_string
+{
+  bool operator()(const dicom_stl::pair<int, dicom_stl::string> s1, 
+                  const dicom_stl::pair<int, dicom_stl::string> s2) const
+  {
+    return s1.first < s2.first;
+  }
+};
+
+
+struct lt_pair_float_string
+{
+  bool operator()(const dicom_stl::pair<float, dicom_stl::string> s1, 
+                  const dicom_stl::pair<float, dicom_stl::string> s2) const
+  {
+    return s1.first < s2.first;
+  }
+};
+
+
+struct gt_pair_int_string
+{
+  bool operator()(const dicom_stl::pair<int, dicom_stl::string> s1, 
+                  const dicom_stl::pair<int, dicom_stl::string> s2) const
+  {
+    return s1.first > s2.first;
+  }
+};
+
+
+struct gt_pair_float_string
+{
+  bool operator()(const dicom_stl::pair<float, dicom_stl::string> s1, 
+                  const dicom_stl::pair<float, dicom_stl::string> s2) const
+  {
+    return s1.first > s2.first;
+  }
+};
+
+
+DICOMAppHelper::DICOMAppHelper()
+{
+  this->FileCount = 0;
+  this->BitsAllocated = 8;
+  this->ByteSwapData = false;
+  this->PixelSpacing[0] = this->PixelSpacing[1] = this->PixelSpacing[2] = 1.0;
+  this->Dimensions[0] = this->Dimensions[1] = 0;
+  this->Width = this->Height = 0;
+  this->PhotometricInterpretation = NULL;
+  this->TransferSyntaxUID = NULL;
+  this->CurrentSeriesUID = "";
+  this->InstanceUID = "";
+  this->RescaleOffset = 0.0;
+  this->RescaleSlope = 1.0;
+  this->ImageData = NULL;
+  this->ImageDataLengthInBytes = 0;
+
+  // Initialize the arrays
+  m_NumberOfSeriesInStudy[0]='\0';
+  m_PatientName[0]='\0';
+  m_PatientID[0]='\0';
+  m_PatientDOB[0]='\0';
+  m_StudyID[0]='\0';
+  m_StudyDescription[0]='\0';
+  m_BodyPart[0]='\0';
+  m_NumberOfSeriesInStudy[0]='\0';
+  m_NumberOfStudyRelatedSeries[0]='\0';
+  m_PatientSex[0]='\0';
+  m_PatientAge[0]='\0';
+  m_StudyDate[0]='\0';
+  m_Modality[0]='\0';
+  m_Manufacturer[0]='\0';
+  m_Institution[0]='\0';
+  m_Model[0]='\0';
+  m_ScanOptions[0]='\0';
+
+
+  this->SeriesUIDCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->SeriesDescriptionCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->InstanceUIDCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->SliceNumberCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->SliceLocationCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ImagePositionPatientCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ImageOrientationPatientCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->TransferSyntaxCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ToggleSwapBytesCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->BitsAllocatedCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->PixelSpacingCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->HeightCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->WidthCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->PixelRepresentationCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->PhotometricInterpretationCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->RescaleOffsetCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->RescaleSlopeCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->PixelDataCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ROIContourSequenceCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ContourImageSequenceCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ContourSequenceCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ContourDataCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->NumberOfContourPointsCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ContourGeometricTypeCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ReferencedInstanceUIDCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->PatientNameCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->PatientIDCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->PatientSexCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->PatientAgeCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->PatientDOBCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->StudyIDCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->StudyDescriptionCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->BodyPartCB  = new DICOMMemberCallback<DICOMAppHelper>;
+  this->NumberOfSeriesInStudyCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->NumberOfStudyRelatedSeriesCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->StudyDateCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ModalityCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ManufacturerCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->InstitutionCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ModelCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->ScanOptionsCB = new DICOMMemberCallback<DICOMAppHelper>;
+  this->DefaultCB = new DICOMMemberCallback<DICOMAppHelper>;
+  
+  this->Implementation = new DICOMAppHelperImplementation;
+}
+
+DICOMAppHelper::~DICOMAppHelper()
+{
+  this->Clear();
+
+  this->HeaderFile.close();
+
+  //
+  // Fix warning here.
+  //
+  if (this->ImageData)
+    {
+    delete [] (static_cast<char*> (this->ImageData));
+    }
+  if (this->TransferSyntaxUID)
+    {
+    delete this->TransferSyntaxUID;
+    }
+  if (this->PhotometricInterpretation)
+    {
+    delete this->PhotometricInterpretation;
+    }
+
+  delete this->SeriesUIDCB;
+  delete this->SeriesDescriptionCB;
+  delete this->InstanceUIDCB;
+  delete this->SliceNumberCB;
+  delete this->SliceLocationCB;
+  delete this->ImagePositionPatientCB;
+  delete this->ImageOrientationPatientCB;
+  delete this->TransferSyntaxCB;
+  delete this->ToggleSwapBytesCB;
+  delete this->BitsAllocatedCB;
+  delete this->PixelSpacingCB;
+  delete this->HeightCB;
+  delete this->WidthCB;
+  delete this->PixelRepresentationCB;
+  delete this->PhotometricInterpretationCB;
+  delete this->RescaleOffsetCB;
+  delete this->RescaleSlopeCB;
+  delete this->PixelDataCB;
+  delete this->ROIContourSequenceCB;
+  delete this->ContourImageSequenceCB;
+  delete this->ContourSequenceCB;
+  delete this->ContourDataCB;
+  delete this->NumberOfContourPointsCB;
+  delete this->ContourGeometricTypeCB;
+  delete this->ReferencedInstanceUIDCB;
+  delete this->PatientNameCB;
+  delete this->PatientIDCB;
+  delete this->PatientSexCB;
+  delete this->PatientAgeCB;
+  delete this->PatientDOBCB;
+  delete this->StudyIDCB;
+  delete this->StudyDescriptionCB;
+  delete this->BodyPartCB;
+  delete this->NumberOfSeriesInStudyCB;
+  delete this->NumberOfStudyRelatedSeriesCB;
+  delete this->StudyDateCB;
+  delete this->ModalityCB;
+  delete this->ManufacturerCB;
+  delete this->InstitutionCB;
+  delete this->ModelCB;
+  delete this->ScanOptionsCB;
+
+  delete this->DefaultCB;
+
+  delete this->Implementation;
+}
+
+void DICOMAppHelper::RegisterCallbacks(DICOMParser* parser)
+{
+  if (!parser)
+    {
+    dicom_stream::cerr << "Null parser!" << dicom_stream::endl;
+    }
+
+  // Default callback. Typically used to register a callback for
+  // sequences where we are not interested in the sequence itself but
+  // an element within the sequence.
+  DefaultCB->SetCallbackFunction(this, &DICOMAppHelper::DefaultCallback);
+
+  //
+  //
+  //
+  SeriesUIDCB->SetCallbackFunction(this, &DICOMAppHelper::SeriesUIDCallback);
+  parser->AddDICOMTagCallback(0x0020, 0x000e, DICOMParser::VR_UI, SeriesUIDCB);
+
+  InstanceUIDCB->SetCallbackFunction(this, &DICOMAppHelper::InstanceUIDCallback);
+  parser->AddDICOMTagCallback(0x0008, 0x0018, DICOMParser::VR_UI, InstanceUIDCB);
+  
+  SeriesDescriptionCB->SetCallbackFunction(this, &DICOMAppHelper::SeriesDescriptionCallback);
+  parser->AddDICOMTagCallback(0x0008, 0x103e, DICOMParser::VR_LO, SeriesDescriptionCB);
+
+  SliceNumberCB->SetCallbackFunction(this, &DICOMAppHelper::SliceNumberCallback);
+  parser->AddDICOMTagCallback(0x0020, 0x0013, DICOMParser::VR_IS, SliceNumberCB);
+
+  SliceLocationCB->SetCallbackFunction(this, &DICOMAppHelper::SliceLocationCallback);
+  parser->AddDICOMTagCallback(0x0020, 0x1041, DICOMParser::VR_DS, SliceLocationCB);
+
+  ImagePositionPatientCB->SetCallbackFunction(this, &DICOMAppHelper::ImagePositionPatientCallback);
+  parser->AddDICOMTagCallback(0x0020, 0x0032, DICOMParser::VR_SH, ImagePositionPatientCB);
+
+  ImageOrientationPatientCB->SetCallbackFunction(this, &DICOMAppHelper::ImageOrientationPatientCallback);
+  parser->AddDICOMTagCallback(0x0020, 0x0037, DICOMParser::VR_SH, ImageOrientationPatientCB);
+  
+  TransferSyntaxCB->SetCallbackFunction(this, &DICOMAppHelper::TransferSyntaxCallback);
+  parser->AddDICOMTagCallback(0x0002, 0x0010, DICOMParser::VR_UI, TransferSyntaxCB);
+
+  ToggleSwapBytesCB->SetCallbackFunction(this, &DICOMAppHelper::ToggleSwapBytesCallback);
+
+  BitsAllocatedCB->SetCallbackFunction(this, &DICOMAppHelper::BitsAllocatedCallback);
+  parser->AddDICOMTagCallback(0x0028, 0x0100, DICOMParser::VR_US, BitsAllocatedCB);
+
+  PixelSpacingCB->SetCallbackFunction(this, &DICOMAppHelper::PixelSpacingCallback);
+  parser->AddDICOMTagCallback(0x0028, 0x0030, DICOMParser::VR_FL, PixelSpacingCB);
+  parser->AddDICOMTagCallback(0x0018, 0x0050, DICOMParser::VR_FL, PixelSpacingCB);
+
+  WidthCB->SetCallbackFunction(this, &DICOMAppHelper::WidthCallback);
+  parser->AddDICOMTagCallback(0x0028, 0x0011, DICOMParser::VR_US, WidthCB);
+
+  HeightCB->SetCallbackFunction(this, &DICOMAppHelper::HeightCallback);
+  parser->AddDICOMTagCallback(0x0028, 0x0010, DICOMParser::VR_US, HeightCB);
+
+  PixelRepresentationCB->SetCallbackFunction(this, &DICOMAppHelper::PixelRepresentationCallback);
+  parser->AddDICOMTagCallback(0x0028, 0x0103, DICOMParser::VR_US, PixelRepresentationCB);
+
+  PhotometricInterpretationCB->SetCallbackFunction(this, &DICOMAppHelper::PhotometricInterpretationCallback);
+  parser->AddDICOMTagCallback(0x0028, 0x0004, DICOMParser::VR_CS, PhotometricInterpretationCB);
+
+  RescaleOffsetCB->SetCallbackFunction(this, &DICOMAppHelper::RescaleOffsetCallback);
+  parser->AddDICOMTagCallback(0x0028, 0x1052, DICOMParser::VR_DS, RescaleOffsetCB);
+
+  RescaleSlopeCB->SetCallbackFunction(this, &DICOMAppHelper::RescaleSlopeCallback);
+  parser->AddDICOMTagCallback(0x0028, 0x1053, DICOMParser::VR_DS, RescaleSlopeCB);
+
+  ROIContourSequenceCB->SetCallbackFunction(this, &DICOMAppHelper::ROIContourSequenceCallback);
+  parser->AddDICOMTagCallback(0x3006, 0x0039, DICOMParser::VR_SQ, ROIContourSequenceCB);
+
+  ContourSequenceCB->SetCallbackFunction(this, &DICOMAppHelper::ContourSequenceCallback);
+  parser->AddDICOMTagCallback(0x3006, 0x0040, DICOMParser::VR_SQ, ContourSequenceCB);
+
+  ContourGeometricTypeCB->SetCallbackFunction(this, &DICOMAppHelper::ContourGeometricTypeCallback);
+  parser->AddDICOMTagCallback(0x3006, 0x0042, DICOMParser::VR_CS, ContourGeometricTypeCB);
+
+  NumberOfContourPointsCB->SetCallbackFunction(this, &DICOMAppHelper::NumberOfContourPointsCallback);
+  parser->AddDICOMTagCallback(0x3006, 0x0046, DICOMParser::VR_IS, NumberOfContourPointsCB);
+
+  ContourDataCB->SetCallbackFunction(this, &DICOMAppHelper::ContourDataCallback);
+  parser->AddDICOMTagCallback(0x3006, 0x0050, DICOMParser::VR_DS, ContourDataCB);
+
+  ContourImageSequenceCB->SetCallbackFunction(this, &DICOMAppHelper::ContourImageSequenceCallback);
+  parser->AddDICOMTagCallback(0x3006, 0x0016, DICOMParser::VR_SQ, ContourImageSequenceCB);
+
+  ReferencedInstanceUIDCB->SetCallbackFunction(this, &DICOMAppHelper::ReferencedInstanceUIDCallback);
+  parser->AddDICOMTagCallback(0x0008, 0x1155, DICOMParser::VR_UI, ReferencedInstanceUIDCB);
+
+  PatientNameCB->SetCallbackFunction(this, &DICOMAppHelper::PatientNameCallback);
+  parser->AddDICOMTagCallback(0x0010, 0x0010, DICOMParser::VR_PN, PatientNameCB);
+
+  PatientIDCB->SetCallbackFunction(this, &DICOMAppHelper::PatientIDCallback);
+  parser->AddDICOMTagCallback(0x0010, 0x0020, DICOMParser::VR_LO, PatientIDCB);
+
+  PatientSexCB->SetCallbackFunction(this, &DICOMAppHelper::PatientSexCallback);
+  parser->AddDICOMTagCallback(0x0010, 0x0040, DICOMParser::VR_CS, PatientSexCB);
+
+  PatientAgeCB->SetCallbackFunction(this, &DICOMAppHelper::PatientAgeCallback);
+  parser->AddDICOMTagCallback(0x0010, 0x1010, DICOMParser::VR_AS, PatientAgeCB);
+ 
+  PatientDOBCB->SetCallbackFunction(this, &DICOMAppHelper::PatientDOBCallback);
+  parser->AddDICOMTagCallback(0x0010, 0x0030, DICOMParser::VR_DA, PatientDOBCB);
+
+  StudyIDCB->SetCallbackFunction(this, &DICOMAppHelper::StudyIDCallback);
+  parser->AddDICOMTagCallback(0x0020, 0x0010, DICOMParser::VR_SH, StudyIDCB);
+
+  StudyDescriptionCB->SetCallbackFunction(this, &DICOMAppHelper::StudyDescriptionCallback);
+  parser->AddDICOMTagCallback(0x0008, 0x1030, DICOMParser::VR_LO, StudyDescriptionCB);
+
+  BodyPartCB->SetCallbackFunction(this, &DICOMAppHelper::BodyPartCallback);
+  parser->AddDICOMTagCallback(0x0018, 0x0015, DICOMParser::VR_CS, BodyPartCB);
+
+  NumberOfSeriesInStudyCB->SetCallbackFunction(this, &DICOMAppHelper::NumberOfSeriesInStudyCallback);
+  parser->AddDICOMTagCallback(0x0020, 0x1000, DICOMParser::VR_IS, NumberOfSeriesInStudyCB);
+
+  NumberOfStudyRelatedSeriesCB->SetCallbackFunction(this, &DICOMAppHelper::NumberOfStudyRelatedSeriesCallback);
+  parser->AddDICOMTagCallback(0x0020, 0x1206, DICOMParser::VR_IS, NumberOfStudyRelatedSeriesCB);
+
+  StudyDateCB->SetCallbackFunction(this, &DICOMAppHelper::StudyDateCallback);
+  parser->AddDICOMTagCallback(0x0008, 0x0020, DICOMParser::VR_DA, StudyDateCB);
+
+  ModalityCB->SetCallbackFunction(this, &DICOMAppHelper::ModalityCallback);
+  parser->AddDICOMTagCallback(0x0008, 0x0060, DICOMParser::VR_CS, ModalityCB);
+
+  ManufacturerCB->SetCallbackFunction(this, &DICOMAppHelper::ManufacturerCallback);
+  parser->AddDICOMTagCallback(0x0008, 0x0070, DICOMParser::VR_LO, ManufacturerCB);
+
+  InstitutionCB->SetCallbackFunction(this, &DICOMAppHelper::InstitutionCallback);
+  parser->AddDICOMTagCallback(0x0008, 0x0080, DICOMParser::VR_LO, InstitutionCB);
+
+  ModelCB->SetCallbackFunction(this, &DICOMAppHelper::ModelCallback);
+  parser->AddDICOMTagCallback(0x0008, 0x1090, DICOMParser::VR_LO, ModelCB);
+
+  ScanOptionsCB->SetCallbackFunction(this, &DICOMAppHelper::ScanOptionsCallback);
+  parser->AddDICOMTagCallback(0x0018, 0x0022, DICOMParser::VR_CS, ScanOptionsCB);
+
+  // Add in default callbacks for tags we need to see but not cache
+  //parser->AddDICOMTagCallback(0x3006, 0x0012, DICOMParser::VR_DS, DefaultCB);
+  DICOMTagInfo dicom_tags[] = {
+    {0x0002, 0x0002, DICOMParser::VR_UI, "Media storage SOP class uid"},
+    {0x0002, 0x0003, DICOMParser::VR_UI, "Media storage SOP inst uid"},
+    {0x0002, 0x0010, DICOMParser::VR_UI, "Transfer syntax uid"},
+    {0x0002, 0x0012, DICOMParser::VR_UI, "Implementation class uid"},
+    {0x0008, 0x0018, DICOMParser::VR_UI, "Image UID"},
+    {0x0008, 0x0020, DICOMParser::VR_DA, "Series date"},
+    {0x0008, 0x0030, DICOMParser::VR_TM, "Series time"},
+    {0x0008, 0x0060, DICOMParser::VR_SH, "Modality"},
+    {0x0008, 0x0070, DICOMParser::VR_SH, "Manufacturer"},
+    {0x0008, 0x0080, DICOMParser::VR_LO, "Institution"},
+    {0x0008, 0x1060, DICOMParser::VR_SH, "Physician"},
+    {0x0008, 0x1090, DICOMParser::VR_LO, "Model"},
+    {0x0008, 0x103E, DICOMParser::VR_LO, "Series description"},
+    {0x0010, 0x0010, DICOMParser::VR_PN, "Patient name"},
+    {0x0010, 0x0020, DICOMParser::VR_LO, "Patient ID"},
+    {0x0010, 0x0040, DICOMParser::VR_CS, "Patient sex"},
+    {0x0010, 0x1010, DICOMParser::VR_AS, "Patient age"},
+    {0x0010, 0x0030, DICOMParser::VR_DA, "Patient Date of birth"},
+    {0x0020, 0x0010, DICOMParser::VR_SH, "Study ID"},
+    {0x0008, 0x1030, DICOMParser::VR_LO, "Study Description"},
+    {0x0018, 0x0015, DICOMParser::VR_CS, "Body Part"},
+    {0x0020, 0x1000, DICOMParser::VR_IS, "Number of series in study"},
+    {0x0020, 0x1206, DICOMParser::VR_IS, "Number of study related series"},
+    {0x0018, 0x0022, DICOMParser::VR_FL, "Scan options"},  
+    {0x0018, 0x0050, DICOMParser::VR_FL, "slice thickness"},
+    {0x0018, 0x0060, DICOMParser::VR_FL, "kV"},
+    {0x0018, 0x0088, DICOMParser::VR_FL, "slice spacing"},
+    {0x0018, 0x1100, DICOMParser::VR_SH, "Recon diameter"},
+    {0x0018, 0x1151, DICOMParser::VR_FL, "mA"},
+    {0x0018, 0x1210, DICOMParser::VR_SH, "Recon kernel"},
+    {0x0020, 0x000d, DICOMParser::VR_UI, "Study UID"},
+    {0x0020, 0x000e, DICOMParser::VR_UI, "Series UID"},
+    {0x0020, 0x0013, DICOMParser::VR_IS, "Image number"},
+    {0x0020, 0x0032, DICOMParser::VR_SH, "Patient position"},
+    {0x0020, 0x0037, DICOMParser::VR_SH, "Patient position cosines"},
+    {0x0020, 0x1041, DICOMParser::VR_SS, "Slice location"},
+    {0x0028, 0x0010, DICOMParser::VR_FL, "Num rows"},
+    {0x0028, 0x0011, DICOMParser::VR_FL, "Num cols"},
+    {0x0028, 0x0030, DICOMParser::VR_FL, "pixel spacing"},
+    {0x0028, 0x0100, DICOMParser::VR_US, "Bits allocated"},
+    {0x0028, 0x0120, DICOMParser::VR_UL, "pixel padding"},
+    {0x0028, 0x1052, DICOMParser::VR_FL, "pixel offset"},
+    {0x3006, 0x0039, DICOMParser::VR_SQ, "ROI Contour Sequence"},
+    {0x3006, 0x0040, DICOMParser::VR_SQ, "Contour Sequence"},
+    {0x3006, 0x0046, DICOMParser::VR_IS, "Number Of Contour Points"},
+    {0x3006, 0x0050, DICOMParser::VR_DS, "Contour Data"}
+  };
+
+  int num_tags = sizeof(dicom_tags)/sizeof(DICOMTagInfo);
+
+#ifdef DEBUG_DICOM_APP_HELPER
+  DICOMMemberCallback<DICOMAppHelper>** callbackArray = new DICOMMemberCallback<DICOMAppHelper>*[num_tags];
+#endif
+
+  for (int j = 0; j < num_tags; j++)
+    {
+    //
+    // Setup internal map.
+    //
+    DICOMTagInfo tagStruct = dicom_tags[j];
+    doublebyte group = tagStruct.group;
+    doublebyte element = tagStruct.element;
+
+    dicom_stl::pair<doublebyte, doublebyte> gePair(group, element);
+    dicom_stl::pair<const dicom_stl::pair<doublebyte, doublebyte>, DICOMTagInfo> mapPair(gePair, tagStruct);
+    this->Implementation->TagMap.insert(mapPair);
+
+#ifdef aDEBUG_DICOM_APP_HELPER
+    //
+    // Make callback
+    //
+    callbackArray[j] = new DICOMMemberCallback<DICOMAppHelper>;
+    callbackArray[j]->SetCallbackFunction(this, &DICOMAppHelper::ArrayCallback);
+    //
+    // Set callback on parser.
+    //
+    parser->AddDICOMTagCallback(group, element,datatype, callbackArray[j]);
+#endif
+
+    }
+
+}
+
+void DICOMAppHelper::DefaultCallback(DICOMParser *,
+                                     doublebyte,
+                                     doublebyte,
+                                     DICOMParser::VRTypes,
+                                     unsigned char*,
+                                     quadbyte)
+{
+#ifdef DEBUG_DICOM_APP_HELPER  
+  dicom_stream::cout << "Default callback " << dicom_stream::endl;
+#endif
+}
+
+void DICOMAppHelper::InstanceUIDCallback(DICOMParser *parser,
+                                       doublebyte,
+                                       doublebyte,
+                                       DICOMParser::VRTypes,
+                                       unsigned char* val,
+                                       quadbyte len) 
+{
+  if (len == 0)
+    {
+#ifdef DEBUG_DICOM_APP_HELPER  
+    dicom_stream::cout << "Instance UID: (EMPTY)" << dicom_stream::endl;
+#endif
+    
+    // empty the string
+    this->InstanceUID = dicom_stl::string();
+
+    // just return, don't bother updating the internal databases of UID's
+    return;
+    }
+  
+  char* newString = (char*) val;
+  dicom_stl::string newStdString(newString);
+
+  // An anonymized UID, generate one
+  if (newStdString == "0.0.0.0")
+    {
+    char fakeUID[2048];
+    sprintf (fakeUID, "%d.%d.%d.%d", 0, 0, 0, ++this->FileCount);
+    newStdString = fakeUID;
+    }
+  // cache the instance UID
+  this->InstanceUID = newStdString;
+  
+#ifdef DEBUG_DICOM_APP_HELPER  
+  dicom_stream::cout << "Instance UID: " << newStdString << dicom_stream::endl;
+#endif
+
+  // Put the instance UID into the internal database mapping instance UIDs
+  // to filenames
+  this->Implementation
+    ->InstanceUIDToFileNameMap.insert(dicom_stl::pair<const dicom_stl::string, dicom_stl::string>(this->InstanceUID, parser->GetFileName() ));
+}
+
+
+void DICOMAppHelper::ReferencedInstanceUIDCallback(DICOMParser *,
+                                                   doublebyte,
+                                                   doublebyte,
+                                                   DICOMParser::VRTypes,
+                                                   unsigned char* val,
+                                                   quadbyte len) 
+{
+  if (len == 0)
+    {
+#ifdef DEBUG_DICOM_APP_HELPER  
+    dicom_stream::cout << "Referenced Instance UID: (EMPTY)" << dicom_stream::endl;
+#endif
+    
+    // just return, don't bother updating the internal databases of UID's
+    return;
+    }
+
+  char* newString = (char*) val;
+  dicom_stl::string newStdString(newString);
+
+#ifdef DEBUG_DICOM_APP_HELPER  
+  dicom_stream::cout << "Referenced Instance UID: " << newStdString << dicom_stream::endl;
+#endif
+  
+  // store the referenced instance UID in the map for this series.
+  // This vector of referenced instance UIDs should be in lock step
+  // with the contours
+  this->Implementation->SeriesUIDToReferencedInstanceUIDMap[this->CurrentSeriesUID].push_back( newStdString );
+}
+
+void DICOMAppHelper::ContourImageSequenceCallback(DICOMParser *,
+                                                  doublebyte,
+                                                  doublebyte,
+                                                  DICOMParser::VRTypes,
+                                                  unsigned char*,
+                                                  quadbyte) 
+{
+  // Add a contour to the list of contours
+  DICOMAppHelperImplementation::ContourType contour;
+  this->Implementation->SeriesUIDToContoursMap[this->CurrentSeriesUID].push_back(contour);
+
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "Contour Image Sequence. " << dicom_stream::endl;
+#endif
+}
+
+void DICOMAppHelper::SeriesUIDCallback(DICOMParser *,
+                                       doublebyte,
+                                       doublebyte,
+                                       DICOMParser::VRTypes,
+                                       unsigned char* val,
+                                       quadbyte len) 
+{
+  if (len == 0)
+    {
+#ifdef DEBUG_DICOM_APP_HELPER  
+    dicom_stream::cout << "Series UID: (EMPTY)" << dicom_stream::endl;
+#endif
+
+    // clear the cached series uid
+    this->CurrentSeriesUID = dicom_stl::string();
+    
+    // just return, don't bother updating the internal databases of UID's
+    return;
+    }
+
+  char* newString = (char*) val;
+  dicom_stl::string newStdString(newString);
+
+  // An anonymized UID, set the the UID to 0.0.0,1
+  if (newStdString == "0.0.0.0")
+    {
+    char fakeUID[2048];
+    sprintf (fakeUID, "%d.%d.%d.%d", 0, 0, 0, 1);
+    newStdString = fakeUID;
+    }
+
+#ifdef DEBUG_DICOM_APP_HELPER  
+  dicom_stream::cout << "Series UID: " << newStdString << dicom_stream::endl;
+#endif
+
+  // Put the series UID into the internal database mapping instance
+  // UIDs to SeriesUIDs
+  this->Implementation
+    ->InstanceUIDToSeriesUIDMap.insert(dicom_stl::pair<const dicom_stl::string, dicom_stl::string>(this->InstanceUID, newStdString ));
+  
+  // Put the series UID into the internal database mapping series UIDs
+  // to InstanceUIDs
+  DICOMAppHelperImplementation::SeriesUIDToInstanceUIDMapType::iterator iiter = this->Implementation->SeriesUIDToInstanceUIDMap.find(newStdString);
+  if ( iiter == this->Implementation->SeriesUIDToInstanceUIDMap.end())
+    {
+    dicom_stl::vector<dicom_stl::string> newVector;
+    
+    newVector.push_back(this->InstanceUID);
+    this->Implementation->SeriesUIDToInstanceUIDMap.insert(dicom_stl::pair<const dicom_stl::string, dicom_stl::vector<dicom_stl::string> > (newStdString, newVector));
+    }
+  else
+    {
+    (*iiter).second.push_back(this->InstanceUID);
+    }
+  
+  // Put the series UID into the internal database mapping series UIDs
+  // to contours
+  DICOMAppHelperImplementation::SeriesUIDToContoursMapType::iterator citer = this->Implementation->SeriesUIDToContoursMap.find(newStdString);
+  if ( citer == this->Implementation->SeriesUIDToContoursMap.end())
+    {
+    DICOMAppHelperImplementation::ContoursVectorType newVector;
+    
+    this->Implementation->SeriesUIDToContoursMap.insert(dicom_stl::pair<const dicom_stl::string, DICOMAppHelperImplementation::ContoursVectorType> (newStdString, newVector));
+    }
+  // Put the series UID into the internal database mapping series UIDs
+  // to referenced instance UIDs
+  DICOMAppHelperImplementation::SeriesUIDToReferencedInstanceUIDMapType::iterator riter = this->Implementation->SeriesUIDToReferencedInstanceUIDMap.find(newStdString);
+  if ( riter == this->Implementation->SeriesUIDToReferencedInstanceUIDMap.end())
+    {
+    DICOMAppHelperImplementation::InstanceUIDVectorType newVector;
+    
+    this->Implementation->SeriesUIDToReferencedInstanceUIDMap.insert(dicom_stl::pair<const dicom_stl::string, DICOMAppHelperImplementation::InstanceUIDVectorType> (newStdString, newVector));
+    }
+  // cache the current series UID
+  this->CurrentSeriesUID = newStdString;
+}
+
+
+void DICOMAppHelper::SeriesDescriptionCallback(DICOMParser *,
+                                       doublebyte,
+                                       doublebyte,
+                                       DICOMParser::VRTypes,
+                                       unsigned char* val,
+                                       quadbyte len ) 
+{
+  if (len == 0)
+    {
+#ifdef DEBUG_DICOM_APP_HELPER  
+    dicom_stream::cout << "Series Description: (EMPTY)" << dicom_stream::endl;
+#endif
+
+    // clear the cached series uid
+    this->CurrentSeriesDescription = dicom_stl::string();
+    
+    // just return, don't bother updating the internal databases of UID's
+    return;
+    }
+
+  char* newString = (char*) val;
+  dicom_stl::string newStdString(newString);
+
+#ifdef DEBUG_DICOM_APP_HELPER  
+  dicom_stream::cout << "Series Description: " << newStdString << dicom_stream::endl;
+#endif
+  // Put the series description into the internal database mapping series UIDs
+  // to InstanceUIDs
+  DICOMAppHelperImplementation::SeriesUIDToSeriesDescriptionMapType::iterator iiter = this->Implementation->SeriesUIDToSeriesDescriptionMap.find(this->CurrentSeriesUID);
+  if ( iiter == this->Implementation->SeriesUIDToSeriesDescriptionMap.end()) // if not found we insert
+    {
+    this->Implementation->SeriesUIDToSeriesDescriptionMap.insert(dicom_stl::pair<const dicom_stl::string, dicom_stl::string> (this->CurrentSeriesUID, newStdString));
+    }
+  this->CurrentSeriesDescription = newStdString;
+}
+
+void DICOMAppHelper::OutputSeries()
+{
+  dicom_stream::cout << dicom_stream::endl << dicom_stream::endl;
+        
+  for (DICOMAppHelperImplementation::SeriesUIDToInstanceUIDMapType::iterator iter = this->Implementation->SeriesUIDToInstanceUIDMap.begin();
+       iter != this->Implementation->SeriesUIDToInstanceUIDMap.end();
+       iter++)
+    {
+    dicom_stream::cout << "SERIES: " << (*iter).first.c_str() << dicom_stream::endl;
+    dicom_stl::vector<dicom_stl::string>& v_ref = (*iter).second;
+             
+    for (dicom_stl::vector<dicom_stl::string>::iterator v_iter = v_ref.begin();
+         v_iter != v_ref.end();
+         v_iter++)
+      {
+      DICOMAppHelperImplementation::InstanceUIDToSliceOrderingMapType::iterator sn_iter = Implementation->InstanceUIDToSliceOrderingMap.find(*v_iter);
+
+      int slice = -1;
+      if (sn_iter != Implementation->InstanceUIDToSliceOrderingMap.end())
+        {
+        slice = (*sn_iter).second.SliceNumber;
+        }
+      dicom_stream::cout << "\t" << (*v_iter).c_str() << " : "
+                         << this->Implementation->InstanceUIDToFileNameMap[*v_iter] << " : ";
+      if (slice != -1)
+        {
+        dicom_stream::cout << " [SliceNumber = " << slice<< "] ";
+        }
+      if (this->Implementation->SeriesUIDToContoursMap[(*iter).first].size() != 0)
+        {
+        dicom_stream::cout << " [Number of contours = "
+                           << this->Implementation->SeriesUIDToContoursMap[(*iter).first].size() << "] ";
+        }
+      dicom_stream::cout << dicom_stream::endl;
+      }
+                
+    }
+}
+
+
+
+
+
+void DICOMAppHelper::ArrayCallback(DICOMParser *parser,
+                                   doublebyte group,
+                                   doublebyte element,
+                                   DICOMParser::VRTypes datatype,
+                                   unsigned char* val,
+                                   quadbyte len) 
+{
+  const char* desc = "No description";
+  
+  TagMapType::iterator iter = this->Implementation->TagMap.find(dicom_stl::pair<doublebyte, doublebyte> (group, element));
+  if (iter != this->Implementation->TagMap.end())
+    {
+    desc = (*iter).second.description;
+    }
+
+  int t2 = int((0x0000FF00 & datatype) >> 8);
+  int t1 = int((0x000000FF & datatype));
+
+  char ct2(t2);
+  char ct1(t1);
+
+    
+  HeaderFile << "(0x";
+
+  HeaderFile.width(4);
+  char prev = HeaderFile.fill('0');
+
+  HeaderFile << dicom_stream::hex << group;
+  HeaderFile << ",0x";
+
+  HeaderFile.width(4);
+  HeaderFile.fill('0');
+    
+  HeaderFile << dicom_stream::hex << element;
+  HeaderFile << ") ";
+
+  HeaderFile.fill(prev);
+  HeaderFile << dicom_stream::dec;
+  HeaderFile << " " << ct1 << ct2 << " ";
+  HeaderFile << "[" << len << " bytes] ";
+  
+  HeaderFile << desc << " : ";
+  
+  unsigned int uival = 0;
+  float fval = 0;
+  double dval = 0;
+  int ival = 0;
+
+  if (val)
+    {
+    switch (datatype)
+      {
+      case DICOMParser::VR_AE:
+      case DICOMParser::VR_AS:
+      case DICOMParser::VR_CS:
+      case DICOMParser::VR_UI:
+      case DICOMParser::VR_DA:
+      case DICOMParser::VR_DS:
+      case DICOMParser::VR_DT:
+      case DICOMParser::VR_LO:
+      case DICOMParser::VR_LT:
+      case DICOMParser::VR_OB: // ordered bytes
+      case DICOMParser::VR_OW: // ordered words
+      case DICOMParser::VR_PN:
+      case DICOMParser::VR_ST:
+      case DICOMParser::VR_TM:
+      case DICOMParser::VR_UN:
+      case DICOMParser::VR_UT:
+      case DICOMParser::VR_SQ: // sequence
+      case DICOMParser::VR_SH: // strings
+      case DICOMParser::VR_IS:
+        HeaderFile << val;
+        break;
+      case DICOMParser::VR_FL: // float
+        fval = static_cast<float> (atof((char*) val));
+        HeaderFile << fval;
+        break;
+      case DICOMParser::VR_FD: // float double
+        fval = static_cast<float> (atof((char*) val));
+        HeaderFile << dval;
+        break;
+      case DICOMParser::VR_UL: // unsigned long
+      case DICOMParser::VR_SL: // signed long
+      case DICOMParser::VR_AT:
+        HeaderFile << uival;
+        break;
+      //case DICOMParser::VR_IS:
+      //  ival = DICOMFile::ReturnAsSignedLong(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); 
+      //  HeaderFile << ival;
+      //  break;
+      case DICOMParser::VR_SS:
+        ival = DICOMFile::ReturnAsSignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); 
+        HeaderFile << ival;
+        break;
+      case DICOMParser::VR_US: // unsigned short
+        uival = DICOMFile::ReturnAsUnsignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian()); 
+        HeaderFile << uival;
+        break;
+      default:
+        HeaderFile << val << dicom_stream::endl;
+        break;
+      }
+    }
+  else
+    {
+    HeaderFile << "NULL";
+    }
+  
+  HeaderFile << dicom_stream::dec << dicom_stream::endl;
+  HeaderFile.fill(prev);
+
+  delete [] val;
+}
+    
+void DICOMAppHelper::SliceNumberCallback(DICOMParser *,
+                                         doublebyte,
+                                         doublebyte,
+                                         DICOMParser::VRTypes,
+                                         unsigned char* val,
+                                         quadbyte len) 
+{
+  // Look for the current instance UID in the map of slice ordering data
+  DICOMAppHelperImplementation::InstanceUIDToSliceOrderingMapType::iterator it;
+  it = this->Implementation->InstanceUIDToSliceOrderingMap.find( this->InstanceUID );
+  if (it == Implementation->InstanceUIDToSliceOrderingMap.end())
+    {
+    // instance UID not found, create a new entry
+    DICOMOrderingElements ord;
+    if (len > 0)
+      {
+      ord.SliceNumber = atoi( (char *) val);
+      }
+
+    // insert into the map
+    this->Implementation->InstanceUIDToSliceOrderingMap.insert(dicom_stl::pair<const dicom_stl::string, DICOMOrderingElements>(this->InstanceUID, ord));
+    }
+  else
+    {
+    // file found, add new values
+    if (len > 0)
+      {
+      (*it).second.SliceNumber = atoi( (char *)val );
+      }
+    }
+
+  // cache the slice number
+  if (len > 0)
+    {
+    this->SliceNumber = atoi( (char *) val);
+    }
+  else
+    {
+    this->SliceNumber = -1; // default to an unset slice number
+    }
+}
+
+
+void DICOMAppHelper::SliceLocationCallback(DICOMParser *,
+                                           doublebyte,
+                                           doublebyte,
+                                           DICOMParser::VRTypes,
+                                           unsigned char* val,
+                                           quadbyte len) 
+{
+  // Look for the current instance UID in the map of slice ordering data
+  DICOMAppHelperImplementation::InstanceUIDToSliceOrderingMapType::iterator it;
+  it = this->Implementation->InstanceUIDToSliceOrderingMap.find( this->InstanceUID );
+  if (it == Implementation->InstanceUIDToSliceOrderingMap.end())
+    {
+    // instance UID not found, create a new entry
+    DICOMOrderingElements ord;
+    if (len > 0)
+      {
+      ord.SliceLocation = (float)atof( (char *) val);
+      }
+
+    // insert into the map
+    this->Implementation->InstanceUIDToSliceOrderingMap.insert(dicom_stl::pair<const dicom_stl::string, DICOMOrderingElements>(this->InstanceUID, ord));
+    }
+  else
+    {
+    // file found, add new values
+    if (len > 0)
+      {
+      (*it).second.SliceLocation = (float)atof( (char *)val );
+      }
+    }
+}
+
+void DICOMAppHelper::ImagePositionPatientCallback(DICOMParser *,
+                                                  doublebyte,
+                                                  doublebyte,
+                                                  DICOMParser::VRTypes,
+                                                  unsigned char* val,
+                                                  quadbyte) 
+{
+  // Look for the current instance UID in the map of slice ordering data
+  DICOMAppHelperImplementation::InstanceUIDToSliceOrderingMapType::iterator it;
+  it = this->Implementation->InstanceUIDToSliceOrderingMap.find( this->InstanceUID );
+  if (it == Implementation->InstanceUIDToSliceOrderingMap.end())
+    {
+    // instance UID not found, create a new entry
+    DICOMOrderingElements ord;
+
+    if (val)
+      {
+      sscanf( (char*)(val), "%f\\%f\\%f",
+              &ord.ImagePositionPatient[0],
+              &ord.ImagePositionPatient[1],
+              &ord.ImagePositionPatient[2] );
+      }
+    else
+      {
+      // no actual position specified, default to the origin
+      ord.ImagePositionPatient[0] = 0.0;
+      ord.ImagePositionPatient[1] = 0.0;
+      ord.ImagePositionPatient[2] = 0.0;
+      }
+      
+    // insert into the map
+    this->Implementation->InstanceUIDToSliceOrderingMap.insert(dicom_stl::pair<const dicom_stl::string, DICOMOrderingElements>(this->InstanceUID, ord));
+
+    // cache the value
+    memcpy( this->ImagePositionPatient, ord.ImagePositionPatient,
+            3*sizeof(float) );
+    }
+  else
+    {
+    if (val)
+      {
+      // file found, add new values
+      sscanf( (char*)(val), "%f\\%f\\%f",
+              &(*it).second.ImagePositionPatient[0],
+              &(*it).second.ImagePositionPatient[1],
+              &(*it).second.ImagePositionPatient[2] );
+      }
+    else
+      {
+      // no actual position specified, default to the origin
+      (*it).second.ImagePositionPatient[0] = 0.0;
+      (*it).second.ImagePositionPatient[1] = 0.0;
+      (*it).second.ImagePositionPatient[2] = 0.0;
+      }
+    
+    // cache the value
+    memcpy( this->ImagePositionPatient, (*it).second.ImagePositionPatient,
+            3*sizeof(float) );
+    }
+}
+
+
+void DICOMAppHelper::ImageOrientationPatientCallback(DICOMParser *,
+                                                     doublebyte,
+                                                     doublebyte,
+                                                     DICOMParser::VRTypes,
+                                                     unsigned char* val,
+                                                     quadbyte) 
+{
+  // Look for the current instance UID in the map of slice ordering data
+  DICOMAppHelperImplementation::InstanceUIDToSliceOrderingMapType::iterator it;
+  it = this->Implementation->InstanceUIDToSliceOrderingMap.find(this->InstanceUID);
+  if (it == Implementation->InstanceUIDToSliceOrderingMap.end())
+    {
+    // instance UID not found, create a new entry
+    DICOMOrderingElements ord;
+    if (val)
+      {
+      sscanf( (char*)(val), "%f\\%f\\%f\\%f\\%f\\%f",
+              &ord.ImageOrientationPatient[0],
+              &ord.ImageOrientationPatient[1],
+              &ord.ImageOrientationPatient[2],
+              &ord.ImageOrientationPatient[3],
+              &ord.ImageOrientationPatient[4],
+              &ord.ImageOrientationPatient[5] );
+      }
+    else
+      {
+      // no orientation defined, default to an standard axial orientation
+      ord.ImageOrientationPatient[0] = 1.0;
+      ord.ImageOrientationPatient[1] = 0.0;
+      ord.ImageOrientationPatient[2] = 0.0;
+      ord.ImageOrientationPatient[3] = 0.0;
+      ord.ImageOrientationPatient[4] = 1.0;
+      ord.ImageOrientationPatient[5] = 0.0;
+      }
+    
+    // insert into the map
+    this->Implementation->InstanceUIDToSliceOrderingMap.insert(dicom_stl::pair<const dicom_stl::string, DICOMOrderingElements>(this->InstanceUID, ord));
+    }
+  else
+    {
+    // file found, add new values
+    if (val)
+      {
+      sscanf( (char*)(val), "%f\\%f\\%f\\%f\\%f\\%f",
+              &(*it).second.ImageOrientationPatient[0],
+              &(*it).second.ImageOrientationPatient[1],
+              &(*it).second.ImageOrientationPatient[2],
+              &(*it).second.ImageOrientationPatient[3],
+              &(*it).second.ImageOrientationPatient[4],
+              &(*it).second.ImageOrientationPatient[5] );
+      }
+    else
+      {
+      // no orientation defined, default to an standard axial orientation
+      (*it).second.ImageOrientationPatient[0] = 1.0;
+      (*it).second.ImageOrientationPatient[1] = 0.0;
+      (*it).second.ImageOrientationPatient[2] = 0.0;
+      (*it).second.ImageOrientationPatient[3] = 0.0;
+      (*it).second.ImageOrientationPatient[4] = 1.0;
+      (*it).second.ImageOrientationPatient[5] = 0.0;
+      }
+    }
+}
+
+
+void DICOMAppHelper::TransferSyntaxCallback(DICOMParser *parser,
+                                            doublebyte,
+                                            doublebyte,
+                                            DICOMParser::VRTypes,
+                                            unsigned char* val,
+                                            quadbyte) 
+{
+
+#ifdef DEBUG_DICOM_APP_HELPER
+#ifdef WIN32
+  char platformByteOrder = 'L';
+#else
+  char platformByteOrder = 'B';
+#endif
+  dicom_stream::cout << "Platform byte order: " << platformByteOrder << dicom_stream::endl;
+#endif
+
+  static const char* TRANSFER_UID_EXPLICIT_BIG_ENDIAN = "1.2.840.10008.1.2.2";
+
+  // Only add the ToggleSwapBytes callback when we need it.
+  if (strcmp(TRANSFER_UID_EXPLICIT_BIG_ENDIAN, (char*) val) == 0)
+    {
+    this->ByteSwapData = true;
+    parser->AddDICOMTagCallback(0x0800, 0x0000, DICOMParser::VR_UNKNOWN, ToggleSwapBytesCB);
+#ifdef DEBUG_DICOM_APP_HELPER
+    dicom_stream::cerr <<"Registering callback for swapping bytes." << dicom_stream::endl;
+#endif
+    }
+  
+  if (this->TransferSyntaxUID)
+    {
+    delete this->TransferSyntaxUID;
+    }
+  this->TransferSyntaxUID = new dicom_stl::string((char*) val);
+
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "Transfer Syntax UID: " << *this->TransferSyntaxUID;
+  dicom_stream::cout << " " << this->TransferSyntaxUIDDescription(this->TransferSyntaxUID->c_str()) << dicom_stream::endl;
+#endif
+}
+
+void DICOMAppHelper::BitsAllocatedCallback(DICOMParser *parser,
+                                           doublebyte,
+                                           doublebyte,
+                                           DICOMParser::VRTypes,
+                                           unsigned char* val,
+                                           quadbyte len) 
+{
+  if (len == 0)
+    {
+    // no value, clear the cached field, return to default BitsAllocated
+    this->BitsAllocated = 8;
+    return;
+    }
+  
+  this->BitsAllocated = parser->GetDICOMFile()->ReturnAsUnsignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian());
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "Bits allocated: " << this->BitsAllocated << dicom_stream::endl;
+#endif
+}
+
+
+void DICOMAppHelper::ToggleSwapBytesCallback(DICOMParser *parser,
+                                             doublebyte,
+                                             doublebyte,
+                                             DICOMParser::VRTypes,
+                                             unsigned char* ,
+                                             quadbyte len) 
+{
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "ToggleSwapBytesCallback" << dicom_stream::endl;
+#endif
+  bool bs = parser->GetDICOMFile()->GetPlatformIsBigEndian();
+  parser->GetDICOMFile()->SetPlatformIsBigEndian(!bs);
+
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "Set byte swap to: " << parser->GetDICOMFile()->GetPlatformIsBigEndian() << dicom_stream::endl;
+#endif
+
+  long pos = parser->GetDICOMFile()->Tell();
+
+  //
+  // The +4 is probably a hack, but it's a guess at the length of the previous field.
+  //
+  parser->GetDICOMFile()->SkipToPos(pos - len + 4);
+}
+
+
+void DICOMAppHelper::PixelSpacingCallback(DICOMParser *parser,
+                                          doublebyte group,
+                                          doublebyte element,
+                                          DICOMParser::VRTypes,
+                                          unsigned char* val,
+                                          quadbyte len) 
+{
+
+  if (group == 0x0028 && element == 0x0030)
+    {
+    float fval = 1.0; // defaul of 1mm
+    if (len > 0)
+      {
+      fval = DICOMFile::ReturnAsFloat(val, parser->GetDICOMFile()->GetPlatformIsBigEndian());
+      this->PixelSpacing[1] = fval;
+      unsigned char * val2 = val;  // search for separator
+      while( *val2 != '\\' && *val2 != 0 ) val2++;
+      if( *val2 == 0 )
+        {
+        dicom_stream::cerr << "Pixel spacing is missing separator!" << dicom_stream::endl;
+        }
+      else
+        {
+        val2++; // start in the character after the delimiter.
+        fval = DICOMFile::ReturnAsFloat(val2, parser->GetDICOMFile()->GetPlatformIsBigEndian());
+        this->PixelSpacing[0] = fval;
+        }
+      }
+    else
+      {
+      this->PixelSpacing[0] = this->PixelSpacing[1] = fval;
+      }
+    }
+  else if (group == 0x0018 && element == 0x0050)
+    {
+    float fval = 1.0; // defaul of 1mm
+    if (len > 0)
+      {
+      fval = DICOMFile::ReturnAsFloat(val, parser->GetDICOMFile()->GetPlatformIsBigEndian());
+      }
+    this->PixelSpacing[2] = fval;
+    }
+}
+
+void DICOMAppHelper::WidthCallback(DICOMParser *parser,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  unsigned short uival = 0;
+
+  if (len > 0)
+    {
+    uival = DICOMFile::ReturnAsUnsignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian());
+    }
+  
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "Width: " << uival << dicom_stream::endl;
+#endif
+
+  this->Width = uival;
+  this->Dimensions[0] = this->Width;
+}
+
+void DICOMAppHelper::HeightCallback(DICOMParser *parser,
+                                    doublebyte,
+                                    doublebyte,
+                                    DICOMParser::VRTypes,
+                                    unsigned char* val,
+                                    quadbyte len) 
+{
+  unsigned short uival = 0;
+
+  if (len > 0)
+    {
+    uival = DICOMFile::ReturnAsUnsignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian());
+    }
+  
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "Height: " << uival << dicom_stream::endl;
+#endif
+  this->Height = uival;
+  this->Dimensions[1] = this->Height;
+}
+
+
+void DICOMAppHelper::PixelRepresentationCallback( DICOMParser *parser,
+                                                  doublebyte,
+                                                  doublebyte,
+                                                  DICOMParser::VRTypes,
+                                                  unsigned char* val,
+                                                  quadbyte len)
+{
+  unsigned short uival = 1; // default of unsigned
+
+  if (len > 0)
+    {
+    uival = DICOMFile::ReturnAsUnsignedShort(val, parser->GetDICOMFile()->GetPlatformIsBigEndian());
+    }
+  
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "Pixel Representation: " << (uival ? "Signed" : "Unsigned") << dicom_stream::endl;
+#endif
+  this->PixelRepresentation = uival;
+}
+
+void DICOMAppHelper::PhotometricInterpretationCallback( DICOMParser *,
+                                                        doublebyte,
+                                                        doublebyte,
+                                                        DICOMParser::VRTypes,
+                                                        unsigned char* val,
+                                                        quadbyte len)
+{
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "Photometric Interpretation: " << (char*) val << dicom_stream::endl;
+#endif
+  if (this->PhotometricInterpretation)
+    {
+    delete this->PhotometricInterpretation;
+    }
+
+  if (len > 0)
+    {
+    this->PhotometricInterpretation = new dicom_stl::string((char*) val);
+    }
+  else
+    {
+    this->PhotometricInterpretation = NULL;
+    }
+}
+
+void DICOMAppHelper::PixelDataCallback( DICOMParser *,
+                                        doublebyte,
+                                        doublebyte,
+                                        DICOMParser::VRTypes,
+                                        unsigned char* data,
+                                        quadbyte len)
+{
+  int numPixels = this->Dimensions[0] * this->Dimensions[1] * this->GetNumberOfComponents();
+
+  // if length was undefined, i.e. 0xffff, then use numpixels
+  if (len == 0xffff)
+    {
+    numPixels = numPixels;
+    }
+  else
+    {
+    // length was specified, but only read up to len bytes (as
+    // opposed to the image size times number of components)
+    if (len < numPixels)
+      {
+      numPixels = len;
+      }
+    if (numPixels < 0)
+      {
+      numPixels = 0;
+      }
+    }
+
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "numPixels : " << numPixels << dicom_stream::endl;
+#endif
+
+  int ptrIncr = int(this->BitsAllocated/8.0);
+
+  unsigned short* ushortInputData = reinterpret_cast<unsigned short*>(data);
+  unsigned char* ucharInputData = data;
+  short* shortInputData = reinterpret_cast<short*> (data);
+
+  float* floatOutputData; // = NULL;
+  
+  bool isFloat = this->RescaledImageDataIsFloat();
+
+  if (isFloat)
+    {
+#ifdef DEBUG_DICOM_APP_HELPER
+    dicom_stream::cout << "Slope and offset are not integer valued : ";
+    dicom_stream::cout << this->RescaleSlope << ", " << this->RescaleOffset << dicom_stream::endl;
+#endif
+    if (this->ImageData)
+      {
+      delete [] (static_cast<char*> (this->ImageData));
+      }
+    this->ImageData = new float[numPixels];
+    floatOutputData = static_cast<float*> (this->ImageData);
+
+    this->ImageDataType = DICOMParser::VR_FL;
+    this->ImageDataLengthInBytes = numPixels * sizeof(float);
+    float newFloatPixel;
+
+    if (ptrIncr == 1)
+      {
+      for (int i = 0; i < numPixels; i++)
+        {
+        newFloatPixel = float(this->RescaleSlope * ucharInputData[i] + this->RescaleOffset);
+        floatOutputData[i] = newFloatPixel;
+        }
+#ifdef DEBUG_DICOM_APP_HELPER
+      dicom_stream::cout << "Did rescale, offset to float from char." << dicom_stream::endl;
+      dicom_stream::cout << numPixels << " pixels." << dicom_stream::endl;
+#endif
+      }
+    else if (ptrIncr == 2)
+      {
+      for (int i = 0; i < numPixels; i++)
+        {
+        newFloatPixel = float(this->RescaleSlope * ushortInputData[i] + this->RescaleOffset);
+        floatOutputData[i] = newFloatPixel;
+        }
+#ifdef DEBUG_DICOM_APP_HELPER
+      dicom_stream::cout << "Did rescale, offset to float from short." << dicom_stream::endl;
+      dicom_stream::cout << numPixels << " pixels." << dicom_stream::endl;
+#endif
+      }
+    }
+  else
+    {
+#ifdef DEBUG_DICOM_APP_HELPER
+    dicom_stream::cout << "Slope and offset are integer valued : ";
+    dicom_stream::cout << this->RescaleSlope << ", " << this->RescaleOffset << dicom_stream::endl;
+#endif
+
+    if (ptrIncr == 1)
+      {
+      if (this->ImageData)
+        {
+        delete [] (static_cast<char*> (this->ImageData));
+        }
+      this->ImageData = new char[numPixels];
+  
+      char*  charOutputData =  static_cast<char*>  (this->ImageData);
+
+      this->ImageDataType = DICOMParser::VR_OB;
+      this->ImageDataLengthInBytes = numPixels * sizeof(char);
+      char newCharPixel;
+
+      for (int i = 0; i < numPixels; i++)
+        {
+        newCharPixel = char(this->RescaleSlope * ucharInputData[i] + this->RescaleOffset);
+        charOutputData[i] = newCharPixel;
+        }
+#ifdef DEBUG_DICOM_APP_HELPER
+      dicom_stream::cout << "Did rescale, offset to char from char." << dicom_stream::endl;
+      dicom_stream::cout << numPixels << " pixels." << dicom_stream::endl;
+#endif
+      }
+    else if (ptrIncr == 2)
+      {
+      if (this->ImageData)
+        {
+        delete [] (static_cast<char*> (this->ImageData));
+        }
+      this->ImageData = new short[numPixels];
+      short* shortOutputData = static_cast<short*> (this->ImageData);
+
+      this->ImageDataType = DICOMParser::VR_OW;
+      this->ImageDataLengthInBytes = numPixels * sizeof(short);
+      short newShortPixel;
+      for (int i = 0; i < numPixels; i++)
+        {
+        newShortPixel = short(this->RescaleSlope * shortInputData[i] + this->RescaleOffset);
+        shortOutputData[i] = newShortPixel;
+        }
+#ifdef DEBUG_DICOM_APP_HELPER
+      dicom_stream::cout << "Did rescale, offset to short from short." << dicom_stream::endl;
+      dicom_stream::cout << numPixels << " pixels." << dicom_stream::endl;
+#endif
+      }
+    }
+}
+
+
+void DICOMAppHelper::ROIContourSequenceCallback( DICOMParser *,
+                                        doublebyte,
+                                        doublebyte,
+                                        DICOMParser::VRTypes,
+                                        unsigned char*,
+                                        quadbyte )
+{
+
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "ROIContourSequence. " << dicom_stream::endl;
+#endif
+
+}
+
+void DICOMAppHelper::ContourSequenceCallback( DICOMParser *,
+                                        doublebyte,
+                                        doublebyte,
+                                        DICOMParser::VRTypes,
+                                        unsigned char*,
+                                        quadbyte)
+{
+  
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "ContourSequence." << dicom_stream::endl;
+#endif
+
+}
+
+void DICOMAppHelper::ContourGeometricTypeCallback( DICOMParser *,
+                                                   doublebyte,
+                                                   doublebyte,
+                                                   DICOMParser::VRTypes,
+                                                   unsigned char*,
+                                                   quadbyte)
+{
+  
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "ContourGeometricType." << dicom_stream::endl;
+#endif
+
+}
+
+void DICOMAppHelper::ContourDataCallback( DICOMParser *,
+                                        doublebyte,
+                                        doublebyte,
+                                        DICOMParser::VRTypes,
+                                        unsigned char* data,
+                                        quadbyte len)
+{
+
+  // If we haven't added a contour yet, then we must have missed the tag
+  // to start the contour
+  if (this->Implementation->SeriesUIDToContoursMap[this->CurrentSeriesUID].size() == 0)
+    {
+    dicom_stream::cerr << "DICOMAppHelper:: Found contour data tag (0x3006, 0x0050) without a matching contour sequence tag (0x3006, 0x0040)." << dicom_stream::endl;
+    }
+  // If the number of points in the contour is zero, then we were not
+  // expecting any data or we missed the tag for the number of contour
+  // points.
+  else if (this->Implementation->SeriesUIDToContoursMap[this->CurrentSeriesUID].back().size() == 0)  // Note the test for equality
+    {
+    dicom_stream::cerr << "DICOMAppHelper:: Found contour data tag (0x3006, 0x0050) without a matching number of contour points tag (0x3006, 0x0046)." << dicom_stream::endl;
+    }
+  else
+    {
+    // read the number of points Contours.back().size()
+    //
+    //
+    unsigned int i;
+    float p;
+    
+    // get a reference to the contour 
+    DICOMAppHelperImplementation::ContourType
+      &contour = this->Implementation->SeriesUIDToContoursMap[this->CurrentSeriesUID].back();
+
+    // read the coordinates. the space for the points has already been
+    // allocated in NumberOfContourPointsCallback().  we just need to
+    // parse the (x, y, z) values and put them in the contour vector.
+    // Points are stored in a vector of floats (x, y, z, x, y, z, ...)
+    //
+
+    // create a temporary (null terminated) buffer that we can tokenize
+    unsigned char *tdata = new unsigned char[len+1];
+    memcpy((char *) tdata, (char *)data, len);
+    tdata[len] = '\0';
+
+    // tokenize and parse the buffer
+    unsigned char *tPtr;
+    tPtr = (unsigned char *)strtok((char *)tdata, "\\");
+    for (i=0; i < contour.size(); i += 3)
+      {
+      sscanf( (char*)(tPtr), "%f", &p);
+      contour[i] = p;
+      tPtr = (unsigned char *)strtok(NULL, "\\");
+      sscanf( (char*)(tPtr), "%f", &p);
+      contour[i+1] = p;
+      tPtr = (unsigned char *)strtok(NULL, "\\");
+      sscanf( (char*)(tPtr), "%f", &p);
+      contour[i+2] = p;
+      tPtr = (unsigned char *)strtok(NULL, "\\");
+      }
+
+    delete [] tdata;
+    }
+
+
+#ifdef DEBUG_DICOM_APP_HELPER
+  DICOMAppHelperImplementation::ContourType contour = this->Implementation->SeriesUIDToContoursMap[this->CurrentSeriesUID].back();
+  dicom_stream::cout << "Contour with " << contour.size() / 3 << " points." << dicom_stream::endl;
+  for (unsigned int i=0; i < contour.size(); i+=3)
+    {
+    dicom_stream::cout << "[" << contour[i] << ", " << contour[i+1] << ", " << contour[i+2] << "]"
+                      << dicom_stream::endl;
+    }
+#endif
+
+}
+
+void DICOMAppHelper::NumberOfContourPointsCallback( DICOMParser *,
+                                                    doublebyte,
+                                                    doublebyte,
+                                                    DICOMParser::VRTypes,
+                                                    unsigned char* data,
+                                                    quadbyte)
+{
+
+  int n;
+  sscanf( (char*)(data), "%d", &n);
+
+
+  // If we haven't added a contour yet, then we must have missed the tag
+  // to start the contour
+  if (this->Implementation->SeriesUIDToContoursMap[this->CurrentSeriesUID].size() == 0)
+    {
+    dicom_stream::cerr << "DICOMAppHelper:: Found number of contour points tag (0x3006, 0x0046) without a matching contour sequence tag (0x3006, 0x0040)." << dicom_stream::endl;
+    }
+  // If the last contour is not empty, then we haven't started the
+  // current contour.  A preceding call to ContourSequenceCallback()
+  // would have created an empty contour at the end of the Contour
+  // list.
+  else if (this->Implementation->SeriesUIDToContoursMap[this->CurrentSeriesUID].back().size() != 0) 
+    {
+    dicom_stream::cerr << "DICOMAppHelper:: Found number of contour points tag (0x3006, 0x0046) without a matching contour geometric type tag (0x3006, 0x0042)." << dicom_stream::endl;
+    }
+  else
+    {
+    // reserve enough space for the points in the contour (3 floats
+    // per point).  note that we trigger off this size later to parse
+    // the coordinates of the contours
+    this->Implementation->SeriesUIDToContoursMap[this->CurrentSeriesUID].back().resize( 3*n ); 
+    }
+  
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "NumberOfContourPoints : " ;
+  dicom_stream::cout << n << dicom_stream::endl;
+#endif
+
+}
+
+
+void DICOMAppHelper::RegisterPixelDataCallback(DICOMParser* parser)
+{
+  this->PixelDataCB->SetCallbackFunction(this, &DICOMAppHelper::PixelDataCallback);
+  parser->AddDICOMTagCallback(0x7FE0, 0x0010, DICOMParser::VR_OW, this->PixelDataCB);
+}
+
+
+const char* DICOMAppHelper::TransferSyntaxUIDDescription(const char* uid)
+{
+  static const char* DICOM_IMPLICIT_VR_LITTLE_ENDIAN = "1.2.840.10008.1.2";
+  static const char* DICOM_LOSSLESS_JPEG = "1.2.840.10008.1.2.4.70";
+  static const char* DICOM_LOSSY_JPEG_8BIT = "1.2.840.10008.1.2.4.50";
+  static const char* DICOM_LOSSY_JPEG_16BIT = "1.2.840.10008.1.2.4.51";
+  static const char* DICOM_EXPLICIT_VR_LITTLE_ENDIAN = "1.2.840.10008.1.2.1";
+  static const char* DICOM_EXPLICIT_VR_BIG_ENDIAN = "1.2.840.10008.1.2.2";
+  static const char* DICOM_GE_PRIVATE_IMPLICIT_BIG_ENDIAN = "1.2.840.113619.5.2";
+
+  if (!strcmp(DICOM_IMPLICIT_VR_LITTLE_ENDIAN, uid))
+    {
+    return "Implicit VR, Little Endian";
+    }
+  else if (!strcmp(DICOM_LOSSLESS_JPEG, uid))
+    {
+    return "Lossless JPEG";
+    }
+  else if (!strcmp(DICOM_LOSSY_JPEG_8BIT, uid))
+    {
+    return "Lossy JPEG 8 bit";
+    }
+  else if (!strcmp(DICOM_LOSSY_JPEG_16BIT, uid))
+    {
+    return "Lossy JPEG 16 bit.";
+    }
+  else if (!strcmp(DICOM_EXPLICIT_VR_LITTLE_ENDIAN, uid))
+    {
+    return "Explicit VR, Little Endian.";
+    }
+  else if (!strcmp(DICOM_EXPLICIT_VR_BIG_ENDIAN, uid))
+    {
+    return "Explicit VR, Big Endian.";
+    }
+  else if (!strcmp(DICOM_GE_PRIVATE_IMPLICIT_BIG_ENDIAN, uid))
+    {
+    return "GE Private, Implicit VR, Big Endian Image Data.";
+    }
+  else
+    {
+    return "Unknown.";
+    }
+
+}
+
+
+void DICOMAppHelper::RescaleOffsetCallback( DICOMParser *parser,
+                                            doublebyte,
+                                            doublebyte,
+                                            DICOMParser::VRTypes,
+                                            unsigned char* val,
+                                            quadbyte len)
+{
+  float fval = 0.0;
+
+  if (len > 0)
+    {
+    fval = DICOMFile::ReturnAsFloat(val, parser->GetDICOMFile()->GetPlatformIsBigEndian());
+    }
+  
+  this->RescaleOffset = fval;
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "Pixel offset: " << this->RescaleOffset << dicom_stream::endl;
+#endif
+}
+
+void DICOMAppHelper::RescaleSlopeCallback(DICOMParser *parser,
+                                          doublebyte,
+                                          doublebyte ,
+                                          DICOMParser::VRTypes ,
+                                          unsigned char* val,
+                                          quadbyte len)
+{
+  float fval = 1.0;
+
+  if (len > 0)
+    {
+    fval = DICOMFile::ReturnAsFloat(val,
+                      parser->GetDICOMFile()->GetPlatformIsBigEndian ());
+    }
+  
+#ifdef DEBUG_DICOM_APP_HELPER
+  dicom_stream::cout << "Rescale slope: " << fval << dicom_stream::endl;
+#endif
+  this->RescaleSlope = fval;
+}
+
+void DICOMAppHelper::PatientNameCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_PatientName, (const char*)val, len1);
+    m_PatientName[len1] = '\0';
+    }
+  else
+    {
+    m_PatientName[0] = '\0';
+    }
+}
+
+void DICOMAppHelper::PatientIDCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_PatientID, (const char*)val, len1);
+    m_PatientID[len1] = '\0';
+    }
+  else
+    {
+    m_PatientID[0] = '\0';
+    }
+}
+
+void DICOMAppHelper::PatientSexCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_PatientSex, (const char*)val, len1);
+    m_PatientSex[len1] = '\0';
+    }
+  else
+    {
+    m_PatientSex[0] = '\0';
+    }
+}
+
+void DICOMAppHelper::PatientAgeCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_PatientAge, (const char*)val, len1);
+    m_PatientAge[len1] = '\0';
+    }
+  else
+    {
+    m_PatientAge[0] = '\0';
+    }
+}
+
+void DICOMAppHelper::PatientDOBCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_PatientDOB, (const char*)val, len1);
+    m_PatientDOB[len1] = '\0';
+    }
+  else
+    {
+    m_PatientDOB[0] = '\0';
+    }
+}
+
+
+void DICOMAppHelper::StudyIDCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_StudyID, (const char*)val, len1);
+    m_StudyID[len1] = '\0';
+    }
+  else
+    {
+    m_StudyID[0] = '\0';
+    }
+}
+
+
+void DICOMAppHelper::StudyDescriptionCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_StudyDescription, (const char*)val, len1);
+    m_StudyDescription[len1] = '\0';
+    }
+  else
+    {
+    m_StudyDescription[0] = '\0';
+    }
+}
+
+void DICOMAppHelper::BodyPartCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_BodyPart, (const char*)val, len1);
+    m_BodyPart[len1] = '\0';
+    }
+  else
+    {
+    m_BodyPart[0] = '\0';
+    return;
+    }
+
+  char* newString = (char*) val;
+  dicom_stl::string newStdString(newString);
+
+#ifdef DEBUG_DICOM_APP_HELPER  
+  dicom_stream::cout << "Body Part: " << newStdString << dicom_stream::endl;
+#endif
+  // Put the series description into the internal database mapping series UIDs
+  // to InstanceUIDs
+  DICOMAppHelperImplementation::SeriesUIDToBodyPartMapType::iterator iiter = this->Implementation->SeriesUIDToBodyPartMap.find(this->CurrentSeriesUID);
+  if ( iiter == this->Implementation->SeriesUIDToBodyPartMap.end()) // if not found we insert
+    {
+    this->Implementation->SeriesUIDToBodyPartMap.insert(dicom_stl::pair<const dicom_stl::string, dicom_stl::string> (this->CurrentSeriesUID, newStdString));
+    }
+  this->CurrentBodyPart = newStdString;
+} 
+
+
+void DICOMAppHelper::NumberOfSeriesInStudyCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_NumberOfSeriesInStudy, (const char*)val, len1);
+    m_NumberOfSeriesInStudy[len1] = '\0';
+    }
+  else
+    {
+    m_NumberOfSeriesInStudy[0] = '\0';
+    }
+}
+
+void DICOMAppHelper::NumberOfStudyRelatedSeriesCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_NumberOfStudyRelatedSeries, (const char*)val, len1);
+    m_NumberOfStudyRelatedSeries[len1] = '\0';
+    }
+  else
+    {
+    m_NumberOfStudyRelatedSeries[0] = '\0';
+    }
+} 
+
+void DICOMAppHelper::StudyDateCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_StudyDate, (const char*)val, len1);
+    m_StudyDate[len1] = '\0';
+    }
+  else
+    {
+    m_StudyDate[0] = '\0';
+    }
+}
+
+void DICOMAppHelper::ModalityCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_Modality, (const char*)val, len1);
+    m_Modality[len1] = '\0';
+    }
+  else
+    {
+    m_Modality[0] = '\0';
+    }
+}
+
+void DICOMAppHelper::ManufacturerCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_Manufacturer, (const char*)val, len1);
+    m_Manufacturer[len1] = '\0';
+    }
+  else
+    {
+    m_Manufacturer[0] = '\0';
+    }
+}
+
+void DICOMAppHelper::InstitutionCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_Institution, (const char*)val, len1);
+    m_Institution[len1] = '\0';
+    }
+  else
+    {
+    m_Institution[0] = '\0';
+    }
+}
+
+void DICOMAppHelper::ModelCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_Model, (const char*)val, len1);
+    m_Model[len1] = '\0';
+    }
+  else
+    {
+    m_Model[0] = '\0';
+    }
+}
+
+
+void DICOMAppHelper::ScanOptionsCallback(DICOMParser *,
+                                   doublebyte,
+                                   doublebyte,
+                                   DICOMParser::VRTypes,
+                                   unsigned char* val,
+                                   quadbyte len)
+{
+  if (val)
+    {
+    quadbyte len1 = (len<512) ? len : 511;
+    strncpy(m_ScanOptions, (const char*)val, len1);
+    m_ScanOptions[len1] = '\0';
+    }
+  else
+    {
+    m_ScanOptions[0] = '\0';
+    return;
+    }
+
+  char* newString = (char*) val;
+  dicom_stl::string newStdString(newString);
+
+#ifdef DEBUG_DICOM_APP_HELPER  
+  dicom_stream::cout << "Scan Options: " << newStdString << dicom_stream::endl;
+#endif
+  // Put the series description into the internal database mapping series UIDs
+  // to InstanceUIDs
+  DICOMAppHelperImplementation::SeriesUIDToScanOptionsMapType::iterator iiter = this->Implementation->SeriesUIDToScanOptionsMap.find(this->CurrentSeriesUID);
+  if ( iiter == this->Implementation->SeriesUIDToScanOptionsMap.end()) // if not found we insert
+    {
+    this->Implementation->SeriesUIDToScanOptionsMap.insert(dicom_stl::pair<const dicom_stl::string, dicom_stl::string> (this->CurrentSeriesUID, newStdString));
+    }
+  this->CurrentScanOptions = newStdString;
+}
+
+bool DICOMAppHelper::RescaledImageDataIsFloat()
+{
+  int s = int(this->RescaleSlope);
+  int o = int(this->RescaleOffset);
+
+  float sf = float(s);
+  float of = float(o);
+
+  double d1 = fabs(sf - this->RescaleSlope);
+  double d2 = fabs(of - this->RescaleOffset);
+
+  if (d1 > 0.0 || d2 > 0.0)
+    {
+    return true;
+    }
+  else
+    {
+    return false;
+    }
+}
+
+void DICOMAppHelper::GetImageData(void*& data, DICOMParser::VRTypes& dataType, unsigned long& len)
+{
+  data = this->ImageData;
+  dataType = this->ImageDataType;
+  len = this->ImageDataLengthInBytes;
+}
+
+bool DICOMAppHelper::RescaledImageDataIsSigned()
+{
+  bool rescaleSigned = (this->RescaleSlope < 0.0);
+  bool pixelRepSigned = (this->PixelRepresentation == 1);
+  bool offsetSigned = (this->RescaleOffset < 0.0);
+ 
+  return (rescaleSigned || pixelRepSigned || offsetSigned);
+}
+
+dicom_stl::string
+DICOMAppHelper::GetFileName( const dicom_stl::string &instanceUID )
+{
+  dicom_stl::string ret("");
+
+  DICOMAppHelperImplementation::InstanceUIDToFileNameMapType::iterator
+    it = this->Implementation->InstanceUIDToFileNameMap.find( instanceUID );
+
+  if (it != this->Implementation->InstanceUIDToFileNameMap.end() )
+    {
+    ret = (*it).second;
+    }
+
+  return ret;
+}
+
+
+void DICOMAppHelper::GetSliceNumberFilenamePairs(const dicom_stl::string &seriesUID,
+                                                 dicom_stl::vector<dicom_stl::pair<int, dicom_stl::string> >& v,
+                                                 bool ascending)
+{
+  v.clear();
+
+  DICOMAppHelperImplementation::SeriesUIDToInstanceUIDMapType::iterator miter  = this->Implementation->SeriesUIDToInstanceUIDMap.find(seriesUID);
+
+  if (miter == this->Implementation->SeriesUIDToInstanceUIDMap.end() )
+    {
+    return;
+    }
+
+  // grab the instance uids for the specified series
+  dicom_stl::vector<dicom_stl::string> instanceUIDs = (*miter).second;
+
+  for (dicom_stl::vector<dicom_stl::string>::iterator instanceIter = instanceUIDs.begin();
+       instanceIter != instanceUIDs.end();
+       instanceIter++)
+       {
+       dicom_stl::pair<int, dicom_stl::string> p;
+       p.second = dicom_stl::string(this->Implementation->InstanceUIDToFileNameMap[*instanceIter]);
+       int slice_number;
+       DICOMAppHelperImplementation::InstanceUIDToSliceOrderingMapType::iterator sn_iter = Implementation->InstanceUIDToSliceOrderingMap.find(*instanceIter);
+       // Only store files that have a valid slice number
+       if (sn_iter != Implementation->InstanceUIDToSliceOrderingMap.end())
+        {
+        slice_number = (*sn_iter).second.SliceNumber;
+        p.first = slice_number;
+        v.push_back(p);
+        }
+       }
+  if (ascending)
+    {
+    dicom_stl::sort(v.begin(), v.end(), lt_pair_int_string());
+    }
+  else
+    {
+    dicom_stl::sort(v.begin(), v.end(), gt_pair_int_string());
+    }
+}
+
+void DICOMAppHelper::GetSliceNumberFilenamePairs(dicom_stl::vector<dicom_stl::pair<int, dicom_stl::string> >& v, bool ascending)
+{
+  // Default to using the first series
+  if (this->Implementation->SeriesUIDToInstanceUIDMap.size() > 0)
+    {
+    this->GetSliceNumberFilenamePairs( (*this->Implementation->SeriesUIDToInstanceUIDMap.begin()).first, v, ascending );
+    }
+  else
+    {
+    v.clear();
+    }
+}
+
+void DICOMAppHelper::GetSliceLocationFilenamePairs(const dicom_stl::string &seriesUID,
+                                                   dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> >& v,
+                                                   bool ascending)
+{
+  v.clear();
+
+  DICOMAppHelperImplementation::SeriesUIDToInstanceUIDMapType::iterator miter  = this->Implementation->SeriesUIDToInstanceUIDMap.find(seriesUID);
+
+  if (miter == this->Implementation->SeriesUIDToInstanceUIDMap.end() )
+    {
+    return;
+    }
+
+  // grab the instance UIDs for the specified series
+  dicom_stl::vector<dicom_stl::string> instanceUIDs = (*miter).second;
+
+  for (dicom_stl::vector<dicom_stl::string>::iterator instanceIter = instanceUIDs.begin();
+       instanceIter != instanceUIDs.end();
+       instanceIter++)
+       {
+       dicom_stl::pair<float, dicom_stl::string> p;
+       p.second = dicom_stl::string(this->Implementation->InstanceUIDToFileNameMap[*instanceIter]);
+       float slice_location;
+       DICOMAppHelperImplementation::InstanceUIDToSliceOrderingMapType::iterator sn_iter = Implementation->InstanceUIDToSliceOrderingMap.find(*instanceIter);
+
+       if (sn_iter != Implementation->InstanceUIDToSliceOrderingMap.end())
+        {
+        slice_location = (*sn_iter).second.SliceLocation;
+        p.first = slice_location;
+        v.push_back(p);
+        }
+       }
+  if (ascending)
+    {
+    dicom_stl::sort(v.begin(), v.end(), lt_pair_float_string());
+    }
+  else
+    {
+    dicom_stl::sort(v.begin(), v.end(), gt_pair_float_string());
+    }
+}
+
+void DICOMAppHelper::GetSliceLocationFilenamePairs(dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> >& v,
+                                                   bool ascending)
+{
+  // Default to using the first series
+  if (this->Implementation->SeriesUIDToInstanceUIDMap.size() > 0)
+    {
+    this->GetSliceLocationFilenamePairs( (*this->Implementation->SeriesUIDToInstanceUIDMap.begin()).first,
+                                         v,
+                                         ascending );
+    }
+  else
+    {
+    v.clear();
+    }
+}
+
+void DICOMAppHelper::GetImagePositionPatientFilenamePairs(const dicom_stl::string &seriesUID, dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> >& v,
+                                                          bool ascending)
+{
+  v.clear();
+
+  DICOMAppHelperImplementation::SeriesUIDToInstanceUIDMapType::iterator miter  = this->Implementation->SeriesUIDToInstanceUIDMap.find(seriesUID);
+
+  if (miter == this->Implementation->SeriesUIDToInstanceUIDMap.end() )
+    {
+    return;
+    }
+
+  // grab the instance UIDs for the specified series
+  dicom_stl::vector<dicom_stl::string> instanceUIDs = (*miter).second;
+
+  for (dicom_stl::vector<dicom_stl::string>::iterator instanceIter = instanceUIDs.begin();
+       instanceIter != instanceUIDs.end();
+       instanceIter++)
+       {
+       dicom_stl::pair<float, dicom_stl::string> p;
+       p.second = dicom_stl::string(this->Implementation->InstanceUIDToFileNameMap[*instanceIter]);
+
+       float image_position;
+       float normal[3];
+       
+       DICOMAppHelperImplementation::InstanceUIDToSliceOrderingMapType::iterator sn_iter = Implementation->InstanceUIDToSliceOrderingMap.find(*instanceIter);
+
+       if (sn_iter != Implementation->InstanceUIDToSliceOrderingMap.end())
+        {
+        // compute the image patient position wrt to the slice image
+        // plane normal
+
+        normal[0] = ((*sn_iter).second.ImageOrientationPatient[1]
+                     * (*sn_iter).second.ImageOrientationPatient[5])
+          - ((*sn_iter).second.ImageOrientationPatient[2]
+             * (*sn_iter).second.ImageOrientationPatient[4]);
+        normal[1] = ((*sn_iter).second.ImageOrientationPatient[2]
+                     * (*sn_iter).second.ImageOrientationPatient[3])
+          - ((*sn_iter).second.ImageOrientationPatient[0]
+             *(*sn_iter).second.ImageOrientationPatient[5]);
+        normal[2] = ((*sn_iter).second.ImageOrientationPatient[0]
+                     * (*sn_iter).second.ImageOrientationPatient[4])
+          - ((*sn_iter).second.ImageOrientationPatient[1]
+             * (*sn_iter).second.ImageOrientationPatient[3]);
+        
+        image_position = (normal[0]*(*sn_iter).second.ImagePositionPatient[0])
+          + (normal[1]*(*sn_iter).second.ImagePositionPatient[1])
+          + (normal[2]*(*sn_iter).second.ImagePositionPatient[2]);
+        p.first = image_position;
+        v.push_back(p);
+        }
+       }
+  if (ascending)
+    {
+    dicom_stl::sort(v.begin(), v.end(), lt_pair_float_string());
+    }
+  else
+    {
+    dicom_stl::sort(v.begin(), v.end(), gt_pair_float_string());
+    }
+}
+
+void DICOMAppHelper::GetImagePositionPatientFilenamePairs(dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> >& v,
+                                                          bool ascending)
+{
+  // Default to using the first series
+  if (this->Implementation->SeriesUIDToInstanceUIDMap.size() > 0)
+    {
+    this->GetImagePositionPatientFilenamePairs( (*this->Implementation->SeriesUIDToInstanceUIDMap.begin()).first, v, ascending );
+    }
+  else
+    {
+    v.clear();
+    }
+}
+
+
+void DICOMAppHelper::GetContours(const dicom_stl::string &seriesUID,
+                                 dicom_stl::vector<dicom_stl::vector<float> >& v)
+{
+  v.clear();
+
+  DICOMAppHelperImplementation::SeriesUIDToContoursMapType::iterator iter = this->Implementation->SeriesUIDToContoursMap.find(seriesUID);
+  
+  if (iter == this->Implementation->SeriesUIDToContoursMap.end() )
+    {
+    return;
+    }
+
+  // All we need to do is copy the contours to the output
+  v = (*iter).second;
+}
+
+void DICOMAppHelper::GetContours(dicom_stl::vector<dicom_stl::vector<float> >& v)
+{
+  // Default to using the first series
+  if (this->Implementation->SeriesUIDToInstanceUIDMap.size() > 0)
+    {
+    this->GetContours( (*this->Implementation->SeriesUIDToInstanceUIDMap.begin()).first, v );
+    }
+  else
+    {
+    v.clear();
+    }
+}
+
+
+void DICOMAppHelper::GetReferencedInstanceUIDs(const dicom_stl::string &seriesUID,
+                                 dicom_stl::vector<dicom_stl::string>& v)
+{
+  v.clear();
+
+  DICOMAppHelperImplementation::SeriesUIDToReferencedInstanceUIDMapType::iterator iter = this->Implementation->SeriesUIDToReferencedInstanceUIDMap.find(seriesUID);
+  
+  if (iter == this->Implementation->SeriesUIDToReferencedInstanceUIDMap.end() )
+    {
+    return;
+    }
+
+  // All we need to do is copy the referenced instanced to the output
+  v = (*iter).second;
+}
+
+void DICOMAppHelper::GetReferencedInstanceUIDs(dicom_stl::vector<dicom_stl::string>& v)
+{
+  // Default to using the first series
+  if (this->Implementation->SeriesUIDToInstanceUIDMap.size() > 0)
+    {
+    this->GetReferencedInstanceUIDs( (*this->Implementation->SeriesUIDToReferencedInstanceUIDMap.begin()).first, v );
+    }
+  else
+    {
+    v.clear();
+    }
+}
+
+
+void DICOMAppHelper::GetSeriesUIDs(dicom_stl::vector<dicom_stl::string> &v)
+{
+  v.clear();
+
+  DICOMAppHelperImplementation::SeriesUIDToInstanceUIDMapType::iterator miter;
+
+  for (miter = this->Implementation->SeriesUIDToInstanceUIDMap.begin(); miter != this->Implementation->SeriesUIDToInstanceUIDMap.end();
+       ++miter)
+    {
+    v.push_back( (*miter).first );
+    }
+}
+
+void DICOMAppHelper::GetSeriesDescriptions(dicom_stl::vector<dicom_stl::string> &v)
+{
+  v.clear();
+
+  DICOMAppHelperImplementation::SeriesUIDToInstanceUIDMapType::iterator miter;
+
+  for (miter = this->Implementation->SeriesUIDToInstanceUIDMap.begin(); miter != this->Implementation->SeriesUIDToInstanceUIDMap.end();
+       ++miter)
+    {
+    DICOMAppHelperImplementation::SeriesUIDToSeriesDescriptionMapType::iterator iiter = this->Implementation->SeriesUIDToSeriesDescriptionMap.find((*miter).first);
+    if ( iiter != this->Implementation->SeriesUIDToSeriesDescriptionMap.end()) // if found we insert
+      {
+      v.push_back( (*iiter).second ); 
+      }
+    else
+      {
+      dicom_stl::string value = "";
+      v.push_back( value );
+      }
+   }
+}
+
+
+void DICOMAppHelper::GetBodyParts(dicom_stl::vector<dicom_stl::string> &v)
+{
+  v.clear();
+
+  DICOMAppHelperImplementation::SeriesUIDToInstanceUIDMapType::iterator miter;
+
+  for (miter = this->Implementation->SeriesUIDToInstanceUIDMap.begin(); miter != this->Implementation->SeriesUIDToInstanceUIDMap.end();
+       ++miter)
+    {
+    DICOMAppHelperImplementation::SeriesUIDToBodyPartMapType::iterator iiter = this->Implementation->SeriesUIDToBodyPartMap.find((*miter).first);
+    if ( iiter != this->Implementation->SeriesUIDToBodyPartMap.end()) // if found we insert
+      {
+      v.push_back( (*iiter).second ); 
+      }
+    else
+      {
+      dicom_stl::string value = "";
+      v.push_back( value );
+      }
+   }
+}
+
+
+void DICOMAppHelper::GetScanOptions(dicom_stl::vector<dicom_stl::string> &v)
+{
+  v.clear();
+
+  DICOMAppHelperImplementation::SeriesUIDToInstanceUIDMapType::iterator miter;
+
+  for (miter = this->Implementation->SeriesUIDToInstanceUIDMap.begin(); miter != this->Implementation->SeriesUIDToInstanceUIDMap.end();
+       ++miter)
+    {
+    DICOMAppHelperImplementation::SeriesUIDToScanOptionsMapType::iterator iiter = this->Implementation->SeriesUIDToScanOptionsMap.find((*miter).first);
+    if ( iiter != this->Implementation->SeriesUIDToScanOptionsMap.end()) // if found we insert
+      {
+      v.push_back( (*iiter).second ); 
+      }
+    else
+      {
+      dicom_stl::string value = "";
+      v.push_back( value );
+      }
+   }
+}
+
+
+
+void DICOMAppHelper::Clear()
+{ 
+  this->Implementation->InstanceUIDToSeriesUIDMap.clear();
+  this->Implementation->InstanceUIDToSliceOrderingMap.clear();
+  this->Implementation->SeriesUIDToInstanceUIDMap.clear();
+  this->Implementation->SeriesUIDToSeriesDescriptionMap.clear();
+  this->Implementation->SeriesUIDToContoursMap.clear();
+  this->Implementation->SeriesUIDToBodyPartMap.clear();
+  this->Implementation->SeriesUIDToScanOptionsMap.clear();
+
+  this->CurrentSeriesUID = "";
+  this->CurrentSeriesDescription = "";
+  this->InstanceUID = "";
+}
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
+
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMAppHelper.h b/Utilities/ITK/Utilities/DICOMParser/DICOMAppHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..3795154cf97156658115e09d15a5adb9e9bebacb
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMAppHelper.h
@@ -0,0 +1,867 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMAppHelper.h,v $
+  Language:  C++
+  Date:      $Date: 2005/05/06 18:53:40 $
+  Version:   $Revision: 1.28 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifndef __DICOM_APP_HELPER_H_
+#define __DICOM_APP_HELPER_H_
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( push, 3 )
+#endif 
+
+#include <vector>
+#include <string>
+
+#include "DICOMConfig.h"
+#include "DICOMTypes.h"
+#include "DICOMCallback.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+class DICOMParser;
+
+// Function object for sorting strings
+struct ltstdstr
+{
+  bool operator()(const dicom_stl::string s1, const dicom_stl::string s2) const
+  {
+    return s1 < s2;
+  }
+};
+
+
+// Helper structure for DICOM elements
+struct DICOMTagInfo
+{
+  doublebyte group;
+  doublebyte element;
+  DICOMParser::VRTypes datatype;
+  const char* description;
+};
+
+// Helper class use for ordering DICOM images based on different
+// (group, element) tags.
+class DICOM_EXPORT DICOMOrderingElements
+{
+public:
+  DICOMOrderingElements()
+    {
+      // Default values to something "valid"
+      SliceNumber = -1;
+      SliceLocation = 0.0;
+      ImagePositionPatient[0] = 0.0;
+      ImagePositionPatient[1] = 0.0;
+      ImagePositionPatient[2] = 0.0;
+      ImageOrientationPatient[0] = 1.0;
+      ImageOrientationPatient[1] = 0.0;
+      ImageOrientationPatient[2] = 0.0;
+      ImageOrientationPatient[3] = 0.0;
+      ImageOrientationPatient[4] = 1.0;
+      ImageOrientationPatient[5] = 0.0;
+    }
+      
+  int SliceNumber;
+  float SliceLocation;
+  float ImagePositionPatient[3];
+  float ImageOrientationPatient[6];
+};
+
+class DICOMAppHelperImplementation;
+
+/**
+ * \class DICOMAppHelper
+ * \brief Class to interface an application to a DICOMParser
+ *
+ * DICOMAppHelper assists an application in communicating with a
+ * DICOMParser. DICOMAppHelper registers a series of callbacks to the
+ * DICOMParser which allows it to cache the information from a DICOM
+ * file in a format that is appropriate for an application to
+ * use. Once a DICOM file is read, an application can query the
+ * DICOMAppHelper for the resolution, pixel size, and pixel data.
+ *
+ * If a DICOMParser scans more than one file, the DICOMAppHelper will
+ * group filesnames by SeriesUID.  This allows an application to pass
+ * a series of DICOM files to the DICOMParser (which via the callback
+ * mechanism allows the DICOMAppHelper to cache information) and then
+ * query the DICOMAppHelper for the files that are from the same
+ * series.  The application can request the filenames for a particular
+ * series to be sorted based on image number, slice location, or
+ * patient position. This allows the DICOMAppHelper to assist an
+ * application is collecting all the images from one series into a
+ * volume.
+ */
+class DICOM_EXPORT DICOMAppHelper
+{
+public:
+  /** Standard constructor */
+  DICOMAppHelper();
+
+  /** Standard destructor */
+  virtual ~DICOMAppHelper();
+
+  /** Callbacks that are registered with the DICOMParser.  The
+   * DICOMParser will call one of these callbacks whenever it
+   * encounters a (group, element) that has an associated callback */
+  virtual void RescaleSlopeCallback(DICOMParser *parser,
+                                     doublebyte group,
+                                    doublebyte element,
+                                    DICOMParser::VRTypes type,
+                                    unsigned char* val,
+                                    quadbyte len);
+
+  virtual void ArrayCallback(DICOMParser *parser,
+                             doublebyte group,
+                             doublebyte element,
+                             DICOMParser::VRTypes type,
+                             unsigned char* val,
+                             quadbyte len);
+  
+  virtual void SliceNumberCallback(DICOMParser *parser,
+                                   doublebyte group,
+                                   doublebyte element,
+                                   DICOMParser::VRTypes type,
+                                   unsigned char* val,
+                                   quadbyte len) ;
+
+  virtual void SliceLocationCallback(DICOMParser *parser,
+                                     doublebyte group,
+                                     doublebyte element,
+                                     DICOMParser::VRTypes type,
+                                     unsigned char* val,
+                                     quadbyte len) ;
+
+  virtual void ImagePositionPatientCallback(DICOMParser *parser,
+                                            doublebyte group,
+                                            doublebyte element,
+                                            DICOMParser::VRTypes type,
+                                            unsigned char* val,
+                                            quadbyte len) ;
+  
+  virtual void ImageOrientationPatientCallback(DICOMParser *parser,
+                                               doublebyte group,
+                                               doublebyte element,
+                                               DICOMParser::VRTypes type,
+                                               unsigned char* val,
+                                               quadbyte len) ;
+  
+  virtual void SeriesUIDCallback(DICOMParser *parser,
+                                 doublebyte group,
+                                 doublebyte element,
+                                 DICOMParser::VRTypes type,
+                                 unsigned char* val,
+                                 quadbyte len) ;
+  
+  virtual void SeriesDescriptionCallback(DICOMParser *parser,
+                                 doublebyte group,
+                                 doublebyte element,
+                                 DICOMParser::VRTypes type,
+                                 unsigned char* val,
+                                 quadbyte len) ;
+
+
+  virtual void InstanceUIDCallback(DICOMParser *parser,
+                                   doublebyte group,
+                                   doublebyte element,
+                                   DICOMParser::VRTypes type,
+                                   unsigned char* val,
+                                   quadbyte len) ;
+  
+  virtual void TransferSyntaxCallback(DICOMParser *parser,
+                                      doublebyte group,
+                                      doublebyte element,
+                                      DICOMParser::VRTypes type,
+                                      unsigned char* val,
+                                      quadbyte len) ;
+  
+  virtual void BitsAllocatedCallback(DICOMParser *parser,
+                                     doublebyte group,
+                                     doublebyte element,
+                                     DICOMParser::VRTypes type,
+                                     unsigned char* val,
+                                     quadbyte len) ;
+  
+  virtual void ToggleSwapBytesCallback(DICOMParser *parser,
+                                       doublebyte,
+                                       doublebyte,
+                                       DICOMParser::VRTypes,
+                                       unsigned char*,
+                                       quadbyte);
+  
+  virtual void PixelSpacingCallback(DICOMParser *parser,
+                                    doublebyte group,
+                                    doublebyte element,
+                                    DICOMParser::VRTypes type,
+                                    unsigned char* val,
+                                    quadbyte len) ;
+
+  virtual void HeightCallback(DICOMParser *parser,
+                              doublebyte group,
+                              doublebyte element,
+                              DICOMParser::VRTypes type,
+                              unsigned char* val,
+                              quadbyte len);
+
+  virtual void WidthCallback( DICOMParser *parser,
+                              doublebyte group,
+                              doublebyte element,
+                              DICOMParser::VRTypes type,
+                              unsigned char* val,
+                              quadbyte len);
+
+  virtual void PixelRepresentationCallback(DICOMParser *parser,
+                                           doublebyte group,
+                                           doublebyte element,
+                                           DICOMParser::VRTypes type,
+                                           unsigned char* val,
+                                           quadbyte len);
+
+  virtual void PhotometricInterpretationCallback(DICOMParser *parser,
+                                                 doublebyte,
+                                                 doublebyte,
+                                                 DICOMParser::VRTypes,
+                                                 unsigned char* val,
+                                                 quadbyte len);
+
+  virtual void PixelDataCallback(DICOMParser *parser,
+                                 doublebyte,
+                                 doublebyte,
+                                 DICOMParser::VRTypes,
+                                 unsigned char* val,
+                                 quadbyte len);
+
+  virtual void RescaleOffsetCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+  virtual void ROIContourSequenceCallback( DICOMParser *parser,
+                                           doublebyte,
+                                           doublebyte,
+                                           DICOMParser::VRTypes,
+                                           unsigned char* val,
+                                           quadbyte);
+
+  virtual void ContourSequenceCallback( DICOMParser *parser,
+                                        doublebyte,
+                                        doublebyte,
+                                        DICOMParser::VRTypes,
+                                        unsigned char* val,
+                                        quadbyte);
+
+  virtual void ContourImageSequenceCallback( DICOMParser *parser,
+                                             doublebyte,
+                                             doublebyte,
+                                             DICOMParser::VRTypes,
+                                             unsigned char* val,
+                                             quadbyte);
+
+  virtual void ContourGeometricTypeCallback( DICOMParser *parser,
+                                             doublebyte,
+                                             doublebyte,
+                                             DICOMParser::VRTypes,
+                                             unsigned char* val,
+                                             quadbyte);
+
+  virtual void NumberOfContourPointsCallback( DICOMParser *parser,
+                                              doublebyte,
+                                              doublebyte,
+                                              DICOMParser::VRTypes,
+                                              unsigned char* val,
+                                              quadbyte);
+  
+  virtual void ContourDataCallback( DICOMParser *parser,
+                                    doublebyte,
+                                    doublebyte,
+                                    DICOMParser::VRTypes,
+                                    unsigned char* val,
+                                    quadbyte);
+
+  virtual void ReferencedInstanceUIDCallback( DICOMParser *parser,
+                                              doublebyte,
+                                              doublebyte,
+                                              DICOMParser::VRTypes,
+                                              unsigned char* val,
+                                              quadbyte);
+
+  virtual void PatientNameCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+  virtual void PatientIDCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+  virtual void PatientSexCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+  virtual void PatientAgeCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+  virtual void PatientDOBCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+   virtual void StudyIDCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+   virtual void StudyDescriptionCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+  
+   virtual void BodyPartCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+   
+   virtual void NumberOfSeriesInStudyCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+    
+   virtual void NumberOfStudyRelatedSeriesCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+  virtual void StudyDateCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+  virtual void ModalityCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+  virtual void ManufacturerCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+  virtual void InstitutionCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+  virtual void ModelCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+   
+  virtual void ScanOptionsCallback( DICOMParser *parser,
+                                      doublebyte,
+                                      doublebyte,
+                                      DICOMParser::VRTypes,
+                                      unsigned char* val,
+                                      quadbyte);
+
+  virtual void DefaultCallback( DICOMParser *parser,
+                                doublebyte,
+                                doublebyte,
+                                DICOMParser::VRTypes,
+                                unsigned char* val,
+                                quadbyte);
+  
+
+  
+  /** Register all the standard callbacks with the DICOM Parser.  This
+   * associates a callback with each (group, element) tag pair in the
+   * header of the file whose data needs to be cached. */
+  virtual void RegisterCallbacks(DICOMParser* parser);
+
+  /** Register a callback for retrieving the pixel data from a DICOM
+   *  file */
+  virtual void RegisterPixelDataCallback(DICOMParser* parser);
+
+
+  /** Output information associated with a DICOM series */
+  void OutputSeries();
+
+
+  /** The next set of methods are for accessing information which is
+   * cached when a DICOM file is processed.  This allows access to
+   * information from the header as well as the pixel data. */
+  
+  
+  /** Get the pixel spacing of the last image processed by the
+   *  DICOMParser */
+  float* GetPixelSpacing()
+    {
+    return this->PixelSpacing;
+    }
+
+  /** Get the image width of the last image processed by the
+   *  DICOMParser */
+  int GetWidth()
+    {
+    return this->Width;
+    }
+
+  /** Get the image height of the last image processed by the
+   *  DICOMParser */
+  int GetHeight()
+    {
+    return this->Height;
+    }
+
+  /** Get the dimensions (width, height) of the last image processed
+   *  by the DICOMParser */
+  int* GetDimensions()
+    {
+    return this->Dimensions;
+    }
+
+  /** Get the (DICOM) x,y,z coordinates of the first pixel in the
+   * image (upper left hand corner) of the last image processed by the
+   * DICOMParser */
+  float *GetImagePositionPatient()
+    {
+      return this->ImagePositionPatient;
+    }
+  
+  
+  /** Get the number of bits allocated per pixel of the last image
+   *  processed by the DICOMParser */
+  int GetBitsAllocated()
+    {
+    return this->BitsAllocated;
+    }
+
+  /** Get the pixel representation of the last image processed by the
+   * DICOMParser. A zero is a unsigned quantity.  A one indicates a
+   * signed quantity. */
+  int GetPixelRepresentation()
+    {
+    return this->PixelRepresentation;
+    }
+
+  /** Get the number of components of the last image processed by the
+   *  DICOMParser. */
+  unsigned int GetNumberOfComponents()
+    {
+    if (!this->PhotometricInterpretation)
+      {
+      return 1;
+      }
+
+    //
+    // DICOM standard says that spaces (0x20) are to
+    // be ignored for CS types.  We don't handle this
+    // well yet.
+    //
+    dicom_stl::string str1(*this->PhotometricInterpretation);
+    dicom_stl::string rgb("RGB ");
+
+    if (str1 == rgb)
+      {
+      return 3;
+      }
+    else
+      {
+      return 1;
+      }
+    }
+
+  /** Get the transfer syntax UID for the last image processed by the
+   *  DICOMParser. */
+  dicom_stl::string GetTransferSyntaxUID()
+    {
+    return *(this->TransferSyntaxUID);
+    }
+
+  /** Get a textual description of the transfer syntax of the last
+   *  image processed by the DICOMParser. */
+  const char* TransferSyntaxUIDDescription(const char* uid);
+
+  /** Get the image data from the last image processed by the
+   * DICOMParser.  The data is only valid if the PixelDataCallback was
+   * registered.
+   * \sa RegisterPixelDataCallback()
+  */
+  void GetImageData(void* & data, DICOMParser::VRTypes& dataType, unsigned long& len);
+
+  /** Determine whether the image data was rescaled (by the
+   *  RescaleSlope tag) to be floating point. */
+  bool RescaledImageDataIsFloat();
+
+  /** Determine whether the image data was rescaled (by the
+   * RescaleSlope tag) to be a signed data type. */
+  bool RescaledImageDataIsSigned();
+
+  /** Get the slice number of the last image processed by the
+      DICOMParser. */
+  int GetSliceNumber()
+    {
+    return this->SliceNumber;
+    }
+
+  /** Get the series UID for the current file. */
+  std::string GetSeriesUID() { return this->CurrentSeriesUID; }
+
+  /** Get the series description for the current file. */
+  std::string GetSeriesDescription() { return this->CurrentSeriesDescription; }
+
+  /** Get the patient name processed by the
+      DICOMParser. */
+  void GetPatientName(char* name)
+    {
+    strcpy(name, m_PatientName);
+    }
+
+  /** Get the patient ID processed by the
+      DICOMParser. */
+  void GetPatientID(char* id)
+    {
+    strcpy(id, m_PatientID);
+    }
+
+  /** Get the patient sex processed by the
+      DICOMParser. */
+  void GetPatientSex(char* sex)
+    {
+    strcpy(sex, m_PatientSex);
+    }
+
+  /** Get the patient age processed by the
+      DICOMParser. */
+  void GetPatientAge(char* age)
+    {
+    strcpy(age, m_PatientAge);
+    }
+
+  /** Get the patient date of birth processed by the
+      DICOMParser. */
+  void GetPatientDOB(char* dob)
+    {
+    strcpy(dob, m_PatientDOB);
+    }
+
+ /** Get the study ID processed by the
+      DICOMParser. */
+  void GetStudyID(char* id)
+    {
+    strcpy(id, m_StudyID);
+    }
+
+ /** Get the description of the study processed by the
+      DICOMParser. */
+  void GetStudyDescription(char* desc)
+    {
+    strcpy(desc, m_StudyDescription);
+    }
+
+ /** Get the body part processed by the
+      DICOMParser. */
+  void GetBodyPart(char* part)
+    {
+    strcpy(part, m_BodyPart);
+    }
+
+  /** Get the number of series in the study processed by the
+      DICOMParser. */
+  void GetNumberOfSeriesInStudy(char* number)
+    {
+    strcpy(number, m_NumberOfSeriesInStudy);
+    }
+
+
+ /** Get the number of study related series processed by the
+      DICOMParser. */
+  void GetNumberOfStudyRelatedSeries(char* number)
+    {
+    strcpy(number, m_NumberOfStudyRelatedSeries);
+    }
+
+  /** Get the study date processed by the
+      DICOMParser. */
+  void GetStudyDate(char* date)
+    {
+    strcpy(date, m_StudyDate);
+    }
+
+  /** Get the modality processed by the
+      DICOMParser. */
+  void GetModality(char* modality)
+    {
+    strcpy(modality, m_Modality);
+    }
+
+  /** Get the manufacturer processed by the
+      DICOMParser. */
+  void GetManufacturer(char* manu)
+    {
+    strcpy(manu, m_Manufacturer);
+    }
+
+  /** Get the institution processed by the
+      DICOMParser. */
+  void GetInstitution(char* ins)
+    {
+    strcpy(ins, m_Institution);
+    }
+
+  /** Get the model processed by the
+      DICOMParser. */
+  void GetModel(char* model)
+    {
+    strcpy(model, m_Model);
+    }
+
+  /** Get the scan options name processed by the
+      DICOMParser. */
+  void GetScanOptions(char* options)
+    {
+    strcpy(options, m_ScanOptions);
+    }
+
+  /** Clear the internal databases. This will reset the internal
+   * databases that are grouping filenames based on SeriesUID's and
+   * ordering filenames based on image locations. */
+  void Clear();
+
+  /** Get the series UIDs for the files processed since the last
+   * clearing of the cache. */
+  void GetSeriesUIDs(dicom_stl::vector<dicom_stl::string> &v); 
+
+  /** Get the series Descriptions for the files processed since the last
+   * clearing of the cache. */
+  void GetSeriesDescriptions(dicom_stl::vector<dicom_stl::string> &v); 
+
+  /** Get the body parts for the files processed since the last
+   * clearing of the cache. */
+  void GetBodyParts(dicom_stl::vector<dicom_stl::string> &v); 
+
+  /** Get the scane options for the files processed since the last
+   * clearing of the cache. */
+  void GetScanOptions(dicom_stl::vector<dicom_stl::string> &v); 
+
+  /** Get the filenames for a series ordered by slice number. */
+  void GetSliceNumberFilenamePairs(const dicom_stl::string &seriesUID,
+                              dicom_stl::vector<dicom_stl::pair<int, dicom_stl::string> > &v,
+                                            bool ascending = true);
+
+  /** Get the filenames for a series order by slice number.  Use the
+      first series by default. */
+  void GetSliceNumberFilenamePairs(dicom_stl::vector<dicom_stl::pair<int, dicom_stl::string> > &v,
+                                   bool ascending = true);
+
+  /* Get the filenames for a series ordered by slice location. */
+  void GetSliceLocationFilenamePairs(const dicom_stl::string &seriesUID,
+                              dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> > &v,
+                                   bool ascending = true);
+
+  /* Get the filenames for a series ordered by slice location. Use the
+   * first series by default. */
+  void GetSliceLocationFilenamePairs(dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> > &v,
+                                   bool ascending = true);
+
+  /* Get the filenames for a series ordered by image position
+     patient. This is the most reliable way to order the images in a
+     series. */
+  void GetImagePositionPatientFilenamePairs(const dicom_stl::string &seriesUID,
+                            dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> > &v,
+                                            bool ascending = true);
+
+  /* Get the filenames for a series ordered by image position
+     patient. This is the most reliable way to order the images in a
+     series. Use the first series by default. */
+  void GetImagePositionPatientFilenamePairs(dicom_stl::vector<dicom_stl::pair<float, dicom_stl::string> > &v,
+                                            bool ascending = true);
+
+  /* Get the contours for a series.  A vector of contours is returned
+  where each contour is a vector of floats (x, y, z, x, y, z, x, y,
+  z...). */
+  void GetContours(const dicom_stl::string &seriesUID,
+                   dicom_stl::vector<dicom_stl::vector<float> > &v);
+
+  /* Get the contours for a series.  A vector of contours is returned
+  where each contour is a vector of floats (x, y, z, x, y, z, x, y,
+  z...). Use the first series by default. */
+  void GetContours(dicom_stl::vector<dicom_stl::vector<float> > &v);
+
+  /* Get the referenced instance UIDs for a series.  A vector of
+   * strings in returned. */
+  void GetReferencedInstanceUIDs(const dicom_stl::string &seriesUID,
+                                 dicom_stl::vector<dicom_stl::string> &v);
+  
+  /* Get the referenced instance UIDs for a series.  A vector of
+   * strings in returned. Use the first series by default. */
+  void GetReferencedInstanceUIDs(dicom_stl::vector<dicom_stl::string> &v);
+
+  /** Get the filename for a specific instance UID */
+  dicom_stl::string GetFileName( const dicom_stl::string &instanceUID );
+  
+ protected:
+  int FileCount;
+  int BitsAllocated;
+  bool ByteSwapData;
+  float PixelSpacing[3];
+  int Width;
+  int Height;
+  int SliceNumber; 
+  int Dimensions[2];
+  float ImagePositionPatient[3];
+
+  short VolumeSliceSize;
+  short VolumeSliceCount;
+  long VolumeVoxelCount;
+  long VolumeSegmentCount;
+
+  char m_PatientName[512];
+  char m_PatientID[512];
+  char m_PatientDOB[512];
+  char m_StudyID[512];   
+  char m_StudyDescription[512];
+  char m_BodyPart[512];
+  char m_NumberOfSeriesInStudy[512];
+  char m_NumberOfStudyRelatedSeries[512];
+  char m_PatientSex[512];
+  char m_PatientAge[512];
+  char m_StudyDate[512];
+  char m_Modality[512];
+  char m_Manufacturer[512];
+  char m_Institution[512];
+  char m_Model[512];
+  char m_ScanOptions[512];
+
+  typedef dicom_stl::map<dicom_stl::pair<doublebyte, doublebyte>, DICOMTagInfo> TagMapType;
+  // TagMapType TagMap;
+
+  dicom_stream::ofstream HeaderFile;
+  
+  // 0 unsigned
+  // 1 2s complement (signed)
+  int PixelRepresentation;
+  dicom_stl::string* PhotometricInterpretation;
+  dicom_stl::string* TransferSyntaxUID;
+  dicom_stl::string CurrentSeriesUID;
+  dicom_stl::string CurrentSeriesDescription;
+  dicom_stl::string CurrentBodyPart;
+  dicom_stl::string CurrentScanOptions;
+  dicom_stl::string InstanceUID;
+  
+  float RescaleOffset;
+  float RescaleSlope;
+  void* ImageData;
+  DICOMParser::VRTypes ImageDataType;
+  unsigned long ImageDataLengthInBytes;
+
+  DICOMMemberCallback<DICOMAppHelper>* SeriesUIDCB;
+  DICOMMemberCallback<DICOMAppHelper>* SeriesDescriptionCB;
+  DICOMMemberCallback<DICOMAppHelper>* InstanceUIDCB;
+  DICOMMemberCallback<DICOMAppHelper>* SliceNumberCB;
+  DICOMMemberCallback<DICOMAppHelper>* SliceLocationCB;
+  DICOMMemberCallback<DICOMAppHelper>* ImagePositionPatientCB;
+  DICOMMemberCallback<DICOMAppHelper>* ImageOrientationPatientCB;
+  DICOMMemberCallback<DICOMAppHelper>* TransferSyntaxCB;
+  DICOMMemberCallback<DICOMAppHelper>* ToggleSwapBytesCB;
+  DICOMMemberCallback<DICOMAppHelper>* BitsAllocatedCB;
+  DICOMMemberCallback<DICOMAppHelper>* PixelSpacingCB;
+  DICOMMemberCallback<DICOMAppHelper>* HeightCB;
+  DICOMMemberCallback<DICOMAppHelper>* WidthCB;
+  DICOMMemberCallback<DICOMAppHelper>* PixelRepresentationCB;
+  DICOMMemberCallback<DICOMAppHelper>* PhotometricInterpretationCB;
+  DICOMMemberCallback<DICOMAppHelper>* RescaleOffsetCB;
+  DICOMMemberCallback<DICOMAppHelper>* RescaleSlopeCB;
+  DICOMMemberCallback<DICOMAppHelper>* PixelDataCB;
+  DICOMMemberCallback<DICOMAppHelper>* ROIContourSequenceCB;
+  DICOMMemberCallback<DICOMAppHelper>* ContourSequenceCB;
+  DICOMMemberCallback<DICOMAppHelper>* ContourDataCB;
+  DICOMMemberCallback<DICOMAppHelper>* NumberOfContourPointsCB;
+  DICOMMemberCallback<DICOMAppHelper>* ContourGeometricTypeCB;
+  DICOMMemberCallback<DICOMAppHelper>* ContourImageSequenceCB;
+  DICOMMemberCallback<DICOMAppHelper>* ReferencedInstanceUIDCB;
+  DICOMMemberCallback<DICOMAppHelper>* DefaultCB;
+
+  DICOMMemberCallback<DICOMAppHelper>* PatientNameCB;
+  DICOMMemberCallback<DICOMAppHelper>* PatientIDCB;
+  DICOMMemberCallback<DICOMAppHelper>* PatientSexCB;
+  DICOMMemberCallback<DICOMAppHelper>* PatientAgeCB;
+  DICOMMemberCallback<DICOMAppHelper>* StudyDateCB;
+  DICOMMemberCallback<DICOMAppHelper>* ModalityCB;
+  DICOMMemberCallback<DICOMAppHelper>* ManufacturerCB;
+  DICOMMemberCallback<DICOMAppHelper>* InstitutionCB;
+  DICOMMemberCallback<DICOMAppHelper>* ModelCB;
+  DICOMMemberCallback<DICOMAppHelper>* ScanOptionsCB;
+  DICOMMemberCallback<DICOMAppHelper>* PatientDOBCB;
+  DICOMMemberCallback<DICOMAppHelper>* StudyIDCB;
+  DICOMMemberCallback<DICOMAppHelper>* StudyDescriptionCB;
+  DICOMMemberCallback<DICOMAppHelper>* BodyPartCB;
+  DICOMMemberCallback<DICOMAppHelper>* NumberOfSeriesInStudyCB;
+  DICOMMemberCallback<DICOMAppHelper>* NumberOfStudyRelatedSeriesCB;
+
+  //
+  // Implementation contains stl templated classes that 
+  // can't be exported from a DLL in Windows. We hide
+  // them in the implementation to get rid of annoying
+  // compile warnings.
+  //
+  DICOMAppHelperImplementation* Implementation;
+
+ private:
+  DICOMAppHelper(const DICOMAppHelper&);  
+  void operator=(const DICOMAppHelper&); 
+    
+};
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
+
+#endif
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMBuffer.cxx b/Utilities/ITK/Utilities/DICOMParser/DICOMBuffer.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..79cfa8b3f0d59e2e11efeb6554f6f4def738071c
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMBuffer.cxx
@@ -0,0 +1,100 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMBuffer.cxx,v $
+  Language:  C++
+  Date:      $Date: 2004/03/21 21:40:03 $
+  Version:   $Revision: 1.2 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( disable : 4710 )
+#pragma warning ( push, 3 )
+#endif 
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <stdio.h>
+#include <string>
+
+#include "DICOMConfig.h"
+#include "DICOMBuffer.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+DICOMBuffer::DICOMBuffer(unsigned char *buffer, long length)
+  : DICOMSource(),
+    Buffer(buffer),
+    Length(length),
+    Position(0)
+{
+}
+
+DICOMBuffer::~DICOMBuffer()
+{
+}
+
+DICOMBuffer::DICOMBuffer(const DICOMBuffer& in)
+  : DICOMSource(in)
+{
+  Buffer = in.Buffer;
+  Length = in.Length;
+  Position = in.Position;
+}
+
+void DICOMBuffer::operator=(const DICOMBuffer& in)
+{
+  DICOMSource::operator=(in);
+
+  Buffer = in.Buffer;
+  Length = in.Length;
+  Position = in.Position;
+}
+
+
+long DICOMBuffer::Tell() 
+{
+  return Position;
+}
+
+void DICOMBuffer::SkipToPos(long increment) 
+{
+  Position = increment;
+}
+
+long DICOMBuffer::GetSize() 
+{
+  return Length;
+}
+
+void DICOMBuffer::Skip(long increment) 
+{
+  Position += increment;
+}
+
+void DICOMBuffer::SkipToStart() 
+{
+  Position = 0;
+}
+
+void DICOMBuffer::Read(void* ptr, long nbytes) 
+{
+  memcpy(ptr, Buffer+Position, nbytes);
+  Position += nbytes;
+}
+
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMBuffer.h b/Utilities/ITK/Utilities/DICOMParser/DICOMBuffer.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a6d9b7eb43d70aa09b446398be32d4736c08c84
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMBuffer.h
@@ -0,0 +1,97 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMBuffer.h,v $
+  Language:  C++
+  Date:      $Date: 2004/03/21 21:40:03 $
+  Version:   $Revision: 1.2 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifndef __DICOMBUFFER_H_
+#define __DICOMBUFFER_H_
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( push, 3 )
+#endif 
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "DICOMTypes.h"
+#include "DICOMConfig.h"
+#include "DICOMSource.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+//
+// DICOM data source that is a memory buffer.
+//
+class DICOM_EXPORT DICOMBuffer : public DICOMSource
+{
+ public:
+  DICOMBuffer(unsigned char *buffer, long length);
+  virtual ~DICOMBuffer();
+  
+  //
+  // Return the position in the buffer.
+  //
+  long Tell();
+  
+  // 
+  // Move to a particular position in the buffer.
+  //
+  void SkipToPos(long);
+  
+  //
+  // Return the size of the buffer.
+  //
+  long GetSize();
+  
+  //
+  // Skip a number of bytes.
+  // 
+  void Skip(long);
+  
+  //
+  // Skip to the beginning of the buffer.
+  //
+  void SkipToStart();
+  
+  //
+  // Read data of length len.
+  //
+  void Read(void* data, long len);
+  
+ protected:
+  DICOMBuffer(const DICOMBuffer&);
+  void operator=(const DICOMBuffer&);  
+
+  unsigned char *Buffer;
+  long Length;
+  long Position;
+  
+private:
+  DICOMBuffer();
+
+};
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
+
+#endif // __DICOMBUFFER_H_
+
+
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMCMakeConfig.h.in b/Utilities/ITK/Utilities/DICOMParser/DICOMCMakeConfig.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..7eaca4c45462974cc6b74fc8b45b990d23f720cb
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMCMakeConfig.h.in
@@ -0,0 +1,11 @@
+
+#ifndef __DICOMCMakeConfig_h_
+#define __DICOMCMakeConfig_h_
+
+#cmakedefine DICOM_DLL
+#cmakedefine DICOM_STATIC
+#cmakedefine DICOM_ANSI_STDLIB
+#cmakedefine DICOM_NO_STD_NAMESPACE
+
+#define DICOMPARSER_NAMESPACE @DICOMPARSER_NAMESPACE@
+#endif
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMCallback.h b/Utilities/ITK/Utilities/DICOMParser/DICOMCallback.h
new file mode 100644
index 0000000000000000000000000000000000000000..cf04a4f1a00fbfa16c8dd38f65c16b60ec144a28
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMCallback.h
@@ -0,0 +1,113 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMCallback.h,v $
+  Language:  C++
+  Date:      $Date: 2005/05/13 19:44:21 $
+  Version:   $Revision: 1.7 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifndef __DICOM_CALLBACK_H_
+#define __DICOM_CALLBACK_H_
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( disable : 4786 )
+#pragma warning ( disable : 4503 )
+#pragma warning ( disable : 4710 )
+#pragma warning ( disable : 4702 )
+#pragma warning ( push, 3 )
+#endif 
+
+#include "DICOMConfig.h"
+#include "DICOMParser.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+//
+// Pure virtual class that specifies the interface
+// for a DICOMCallback.  
+//
+// The DICOMParser allows a vector of callbacks to 
+// be specified for each group element tag.  When 
+// a group, element with a registered callback is 
+// encountered, the callback is called and passed
+// the group, element, type, data, and data length.
+//
+
+class DICOM_EXPORT DICOMCallback
+{
+ public:
+  virtual void Execute(DICOMParser *parser,
+                       doublebyte group,
+                       doublebyte element,
+                       DICOMParser::VRTypes type,
+                       unsigned char* val,
+                       quadbyte len) = 0;
+  virtual ~DICOMCallback() {}
+};
+
+//
+// Subclass of DICOMCallback which can be used
+// with member functions.
+//
+template <class T>
+class DICOMMemberCallback : public DICOMCallback
+{
+ public:
+  typedef  void (T::*TMemberFunctionPointer)(DICOMParser *parser,
+                                             doublebyte group,
+                                             doublebyte element,
+                                             DICOMParser::VRTypes type,
+                                             unsigned char* val,
+                                             quadbyte len);
+
+        
+  //
+  // Method to set the object and member function pointers
+  // that will be called in the callback.
+  //
+  void SetCallbackFunction(T* object,  
+                           TMemberFunctionPointer memberFunction)
+  {
+    ObjectThis = object;
+    MemberFunction = memberFunction;
+  }
+ 
+  //
+  // Execute method implementation from DICOMCallback.
+  //
+  void Execute(DICOMParser *parser,
+               doublebyte group,
+               doublebyte element,
+               DICOMParser::VRTypes type,
+               unsigned char* val,
+               quadbyte len)
+  {
+    if (MemberFunction)
+      {
+      ((*ObjectThis).*(MemberFunction))(parser, group, element, type, val,len);
+      }
+  }
+
+ protected:
+  T* ObjectThis;
+  TMemberFunctionPointer MemberFunction;
+
+};
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
+
+#endif
+
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMConfig.h b/Utilities/ITK/Utilities/DICOMParser/DICOMConfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..c31fd7aa098b398e782faad7a9129ec1a7a3a551
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMConfig.h
@@ -0,0 +1,74 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMConfig.h,v $
+  Language:  C++
+  Date:      $Date: 2004/03/22 15:25:59 $
+  Version:   $Revision: 1.4 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifndef __DICOM_CONFIG_H_
+#define __DICOM_CONFIG_H_
+
+//
+// CMake Hook
+//
+#include "DICOMCMakeConfig.h"
+
+//
+// BEGIN Toolkit (ITK,VTK, etc) specific
+// 
+#ifdef vtkDICOMParser_EXPORTS
+  #define DICOM_EXPORT_SYMBOLS
+#endif
+
+#ifdef ITKDICOMParser_EXPORTS
+  #define DICOM_EXPORT_SYMBOLS
+#endif
+
+//
+// END toolkit (ITK, VTK, etc) specific
+//
+
+#ifdef DICOM_NO_STD_NAMESPACE
+  #define dicom_stl
+#else
+  #define dicom_stl std
+#endif
+
+#ifdef DICOM_ANSI_STDLIB
+  #define dicom_stream std
+
+  #include <iostream>
+  #include <fstream>
+  #include <iomanip>
+#else
+  #define dicom_stream 
+
+  #include <iostream.h>
+  #include <fstream.h>
+  #include <iomanip.h>
+#endif
+
+#ifdef DICOM_DLL
+  #ifdef DICOM_EXPORT_SYMBOLS
+    #define DICOM_EXPORT __declspec(dllexport)
+    #define DICOM_EXPIMP_TEMPLATE 
+  #else
+    #define DICOM_EXPORT __declspec(dllimport)
+    #define DICOM_EXPIMP_TEMPLATE extern
+  #endif
+#else
+  #define DICOM_EXPORT 
+#endif
+
+#endif // __DICOM_CONFIG_H_
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMFile.cxx b/Utilities/ITK/Utilities/DICOMParser/DICOMFile.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..36cf29422c583b8ec84e51d2f39c6bf791c70eb6
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMFile.cxx
@@ -0,0 +1,128 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMFile.cxx,v $
+  Language:  C++
+  Date:      $Date: 2004/03/21 21:40:03 $
+  Version:   $Revision: 1.20 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( disable : 4710 )
+#pragma warning ( push, 3 )
+#endif 
+
+#include <stdio.h>
+#include <string>
+
+#include "DICOMConfig.h"
+#include "DICOMFile.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+DICOMFile::DICOMFile() : DICOMSource(), InputStream()
+{
+}
+
+DICOMFile::~DICOMFile()
+{
+  this->Close();
+}
+
+DICOMFile::DICOMFile(const DICOMFile& in)
+  : DICOMSource(in)
+{
+  //
+  // Some compilers can't handle. Comment out for now.
+  //
+  // InputStream = in.InputStream;
+}
+
+void DICOMFile::operator=(const DICOMFile& in)
+{
+  DICOMSource::operator=(in);
+
+  //
+  // Some compilers can't handle. Comment out for now.
+  //
+  // InputStream = in.InputStream;
+}
+
+bool DICOMFile::Open(const dicom_stl::string& filename)
+{
+#ifdef _WIN32
+  InputStream.open(filename.c_str(), dicom_stream::ios::binary | dicom_stream::ios::in);
+#else  
+  InputStream.open(filename.c_str(), dicom_stream::ios::in);
+#endif
+
+  //if (InputStream.is_open())
+  if (InputStream.rdbuf()->is_open())
+    {
+    return true;
+    }
+  else
+    {
+    return false;
+    }
+}
+
+void DICOMFile::Close()
+{
+  InputStream.close();
+}
+
+long DICOMFile::Tell() 
+{
+  long loc = InputStream.tellg();
+  // dicom_stream::cout << "Tell: " << loc << dicom_stream::endl;
+  return loc;
+}
+
+void DICOMFile::SkipToPos(long increment) 
+{
+  InputStream.seekg(increment, dicom_stream::ios::beg);
+}
+
+long DICOMFile::GetSize() 
+{
+  long curpos = this->Tell();
+
+  InputStream.seekg(0,dicom_stream::ios::end);
+
+  long size = this->Tell();
+  // dicom_stream::cout << "Tell says size is: " << size << dicom_stream::endl;
+  this->SkipToPos(curpos);
+
+  return size;
+}
+
+void DICOMFile::Skip(long increment) 
+{
+  InputStream.seekg(increment, dicom_stream::ios::cur);
+}
+
+void DICOMFile::SkipToStart() 
+{
+  InputStream.seekg(0, dicom_stream::ios::beg);
+}
+
+void DICOMFile::Read(void* ptr, long nbytes) 
+{
+  InputStream.read((char*)ptr, nbytes);
+  // dicom_stream::cout << "DICOMFile::Read " <<  (char*) ptr << dicom_stream::endl;
+}
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMFile.h b/Utilities/ITK/Utilities/DICOMParser/DICOMFile.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d4345cace9f838e189844299abd208ba119c7e5
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMFile.h
@@ -0,0 +1,108 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMFile.h,v $
+  Language:  C++
+  Date:      $Date: 2004/03/21 21:40:03 $
+  Version:   $Revision: 1.21 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifndef __DICOMFILE_H_
+#define __DICOMFILE_H_
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( push, 3 )
+#endif 
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+
+#include "DICOMTypes.h"
+#include "DICOMConfig.h"
+#include "DICOMSource.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+//
+// DICOM data source that is file.
+//
+class DICOM_EXPORT DICOMFile : public DICOMSource
+{
+ public:
+  DICOMFile();
+  virtual ~DICOMFile();
+  
+  //
+  // Open a file with filename.  Returns a bool
+  // that is true if the file is successfully
+  // opened.
+  //
+  bool Open(const dicom_stl::string& filename);
+  
+  //
+  // Close a file.
+  //
+  void Close();
+  
+  //
+  // Return the position in the file.
+  //
+  long Tell();
+  
+  // 
+  // Move to a particular position in the file.
+  //
+  void SkipToPos(long);
+  
+  //
+  // Return the size of the file.
+  //
+  long GetSize();
+  
+  //
+  // Skip a number of bytes.
+  // 
+  void Skip(long);
+  
+  //
+  // Skip to the beginning of the file.
+  //
+  void SkipToStart();
+  
+  //
+  // Read data of length len.
+  //
+  void Read(void* data, long len);
+  
+ protected:
+  DICOMFile(const DICOMFile&);
+  void operator=(const DICOMFile&);  
+
+  //
+  // Internal storage for the file pointer.
+  //
+  dicom_stream::ifstream InputStream;
+  
+
+ private:
+
+};
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
+
+#endif // __DICOMFILE_H_
+
+
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMParser.cxx b/Utilities/ITK/Utilities/DICOMParser/DICOMParser.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c6ad302a94363037afa8bf4c81cda266dc625369
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMParser.cxx
@@ -0,0 +1,866 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMParser.cxx,v $
+  Language:  C++
+  Date:      $Date: 2005/07/25 00:13:49 $
+  Version:   $Revision: 1.37 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( disable : 4786 )
+#pragma warning ( disable : 4503 )
+#pragma warning ( disable : 4710 )
+#pragma warning ( push, 3 )
+#endif 
+
+
+#include <stdlib.h>
+#if !defined(__MWERKS__)
+#include <math.h>
+#endif
+#include <time.h>
+#include <assert.h>
+#if !defined(__MWERKS__)
+#include <sys/types.h>
+#endif
+
+#include <string>
+#include <map>
+
+#include "DICOMConfig.h"
+#include "DICOMParser.h"
+#include "DICOMCallback.h"
+#include "DICOMBuffer.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+
+// Define DEBUG_DICOM to get debug messages sent to dicom_stream::cerr
+// #define DEBUG_DICOM
+
+#define DICOMPARSER_IGNORE_MAGIC_NUMBER
+
+#ifdef DEBUG_DICOM
+#define DICOM_DBG_MSG(x) {dicom_stream::cout x}
+#else 
+#define DICOM_DBG_MSG(x)
+#endif
+
+static const char* DICOM_MAGIC = "DICM";
+static const int   OPTIONAL_SKIP = 128;
+
+class DICOMParserImplementation 
+{
+public:
+  DICOMParserImplementation() : Groups(), Elements(), Datatypes(), Map(), TypeMap()
+  {
+
+  };
+
+  dicom_stl::vector<doublebyte> Groups;
+  dicom_stl::vector<doublebyte> Elements;
+  dicom_stl::vector<DICOMParser::VRTypes> Datatypes;
+  //
+  // Stores a map from pair<group, element> keys to
+  // values of pair<vector<DICOMCallback*>, datatype>
+  //
+  DICOMParserMap Map;
+
+  //
+  // Stores a map from pair<group, element> keys to
+  // values of datatype.  We use this to store the 
+  // datatypes for implicit keys that we are 
+  // interested in.
+  //
+  DICOMImplicitTypeMap TypeMap;
+
+};
+
+DICOMParser::DICOMParser() : ParserOutputFile()
+{
+  this->Implementation = new DICOMParserImplementation();
+  this->DataFile = NULL;
+  this->ToggleByteSwapImageData = false;
+  this->TransferSyntaxCB = new DICOMMemberCallback<DICOMParser>;
+  this->InitTypeMap();
+  this->FileName = "";
+}
+
+const dicom_stl::string&
+DICOMParser::GetFileName()
+{
+  return this->FileName;
+}
+
+bool DICOMParser::OpenFile(const dicom_stl::string& filename)
+{
+  if (this->DataFile)
+    {
+    // Deleting the DataFile closes the file
+    delete this->DataFile;
+    }
+  this->DataFile = new DICOMFile();
+  bool val = this->DataFile->Open(filename);
+
+  if (val)
+    {
+    this->FileName = filename;
+    }
+
+  
+#ifdef DEBUG_DICOM
+  if (this->ParserOutputFile.rdbuf()->is_open())
+    {
+    this->ParserOutputFile.flush();
+    this->ParserOutputFile.close();
+    }
+
+  dicom_stl::string fn(filename);
+  dicom_stl::string append(".parser.txt");
+  dicom_stl::string parseroutput(fn + append);
+  // dicom_stl::string parseroutput(dicom_stl::string(dicom_stl::string(filename) + dicom_stl::string(".parser.txt")));
+  this->ParserOutputFile.open(parseroutput.c_str()); //, dicom_stream::ios::app);
+#endif
+ 
+  return val;
+}
+
+DICOMParser::~DICOMParser() {
+  //
+  // Delete the callbacks.
+  //
+  this->ClearAllDICOMTagCallbacks();
+
+  if (this->DataFile)
+    {
+    delete this->DataFile;
+    }
+
+  delete this->TransferSyntaxCB;
+  delete this->Implementation;
+
+#ifdef DEBUG_DICOM
+  this->ParserOutputFile.flush();
+  this->ParserOutputFile.close();
+#endif
+
+}
+
+bool DICOMParser::ReadHeader()
+{
+  return this->ReadHeader(*this->DataFile);
+}
+
+bool DICOMParser::ReadHeader(DICOMSource &source)
+{
+  bool dicom = this->IsDICOMFile(source);
+  if (!dicom)
+    {
+    return false;
+    }
+
+  this->TransferSyntaxCB->SetCallbackFunction(this, &DICOMParser::TransferSyntaxCallback);
+  this->AddDICOMTagCallback(0x0002, 0x0010, DICOMParser::VR_UI, this->TransferSyntaxCB);
+
+  this->ToggleByteSwapImageData = false;
+
+  doublebyte group = 0;
+  doublebyte element = 0;
+  DICOMParser::VRTypes datatype = DICOMParser::VR_UNKNOWN;
+
+  this->Implementation->Groups.clear();
+  this->Implementation->Elements.clear();
+  this->Implementation->Datatypes.clear();
+
+  long fileSize = source.GetSize();
+  do 
+    {
+    this->ReadNextRecord(source, group, element, datatype);
+
+    this->Implementation->Groups.push_back(group);
+    this->Implementation->Elements.push_back(element);
+    this->Implementation->Datatypes.push_back(datatype);
+
+    } while ((source.Tell() >= 0) && (source.Tell() < fileSize));
+
+  return true;
+}
+
+//
+// read magic number from file
+// return true if this is your image type, false if it is not
+//
+bool DICOMParser::IsDICOMFile(DICOMSource &source)
+{
+  char magic_number[4];    
+  magic_number[0] = magic_number[1] = magic_number[2] = magic_number[3] = 'x';
+  source.SkipToStart();
+  source.Read((void*)magic_number,4);
+  if (CheckMagic(magic_number)) 
+    {
+    return(true);
+    } 
+  // try with optional skip
+  else 
+    {
+    source.Skip(OPTIONAL_SKIP-4);
+    source.Read((void*)magic_number,4);
+    if (CheckMagic(magic_number)) 
+      {
+      return true;
+      }
+    else
+      {
+
+#ifndef DICOMPARSER_IGNORE_MAGIC_NUMBER
+      return false;
+#else
+      //
+      // Try it anyways...
+      //
+
+      source.SkipToStart();
+
+      doublebyte group = source.ReadDoubleByte();
+      bool dicom;
+      if (group == 0x0002 || group == 0x0008)
+        {
+        dicom_stream::cerr << "No DICOM magic number found, but file appears to be DICOM." << dicom_stream::endl;
+        dicom_stream::cerr << "Proceeding without caution."  << dicom_stream::endl;
+        dicom = true;
+        }
+      else
+        {
+        dicom = false;
+        }
+      source.SkipToStart();
+
+      return dicom;
+#endif  // DICOMPARSER_IGNORE_MAGIC_NUMBER
+
+      }
+    }
+}
+
+
+bool DICOMParser::IsValidRepresentation(DICOMSource &source, doublebyte rep, quadbyte& len, VRTypes &mytype)
+{
+  switch (rep)
+    {
+    case DICOMParser::VR_AW: 
+    case DICOMParser::VR_AE: 
+    case DICOMParser::VR_AS: 
+    case DICOMParser::VR_CS:
+    case DICOMParser::VR_UI:
+    case DICOMParser::VR_DA:
+    case DICOMParser::VR_DS:
+    case DICOMParser::VR_DT:
+    case DICOMParser::VR_IS:
+    case DICOMParser::VR_LO:
+    case DICOMParser::VR_LT:
+    case DICOMParser::VR_PN:
+    case DICOMParser::VR_ST:
+    case DICOMParser::VR_TM:
+    case DICOMParser::VR_UT: // new
+    case DICOMParser::VR_SH: 
+    case DICOMParser::VR_FL:
+    case DICOMParser::VR_SL:
+    case DICOMParser::VR_AT: 
+    case DICOMParser::VR_UL: 
+    case DICOMParser::VR_US:
+    case DICOMParser::VR_SS:
+    case DICOMParser::VR_FD:
+      len = source.ReadDoubleByte();
+      mytype = VRTypes(rep);
+      return true;
+
+    case DICOMParser::VR_OB: // OB - LE
+    case DICOMParser::VR_OW:
+    case DICOMParser::VR_UN:      
+      source.ReadDoubleByte();
+      len = source.ReadQuadByte();
+      mytype = VRTypes(rep);
+      return true;
+    case DICOMParser::VR_SQ:
+      source.ReadDoubleByte();
+      len = source.ReadQuadByte();
+      mytype = VRTypes(rep);
+      return true;
+
+    default:
+      //
+      //
+      // Need to comment out in new paradigm.
+      //
+      source.Skip(-2);
+      len = source.ReadQuadByte();
+      mytype = DICOMParser::VR_UNKNOWN;
+      return false;  
+    }
+}
+
+
+void DICOMParser::ReadNextRecord(DICOMSource &source, doublebyte& group, doublebyte& element,
+                                 DICOMParser::VRTypes& mytype)
+{
+  // dicom_stream::cout << "ReadNextRecord() " << dicom_stream::endl;
+
+  group = source.ReadDoubleByte();
+  element = source.ReadDoubleByte();
+
+  //dicom_stream::cout << "(" << dicom_stream::hex << group << ", " << element << ") : " ;
+  
+  doublebyte representation = source.ReadDoubleByteAsLittleEndian();
+  quadbyte length = 0;
+  mytype = DICOMParser::VR_UNKNOWN;
+  this->IsValidRepresentation(source, representation, length, mytype);
+
+//   dicom_stream::cout << "representation = " << representation << dicom_stream::dec << ", length = " << length
+//                      << dicom_stream::endl;
+  
+  DICOMParserMap::iterator iter = 
+    Implementation->Map.find(DICOMMapKey(group,element));
+
+  VRTypes callbackType;
+
+  if (iter != Implementation->Map.end())
+    {
+    //
+    // Only read the data if there's a registered callback.
+    //
+    unsigned char* tempdata;
+
+    if (static_cast<unsigned long>(length) != static_cast<unsigned long>(-1))
+      {
+      // length was specified
+      tempdata = (unsigned char*) source.ReadAsciiCharArray(length);
+      }
+    else
+      {
+      // unspecified length, read block as sequence
+      doublebyte dataelementtag[2];
+      quadbyte itemLength;
+
+      dataelementtag[0] = source.ReadDoubleByte();
+      dataelementtag[1] = source.ReadDoubleByte();
+      while (dataelementtag[0] == 0xfffe && dataelementtag[1] == 0xe000) // item tag
+        {
+        //dicom_stream::cout << "Item tag: ";
+        
+        // read the length of the buffer
+        itemLength = source.ReadQuadByte();
+        //dicom_stream::cout << itemLength << dicom_stream::endl;
+        
+        // read the buffer
+        if (itemLength != 0)
+          {
+          tempdata = (unsigned char *) source.ReadAsciiCharArray(itemLength);
+          // should accumulate the block of memory in case the image
+          // is broken into several items
+          }
+
+        // read the delimination tag
+        dataelementtag[0] = source.ReadDoubleByte();
+        dataelementtag[1] = source.ReadDoubleByte();
+        }
+      // check for sequence delimination item
+      if (dataelementtag[0] == 0xfffe && dataelementtag[1] == 0xe0dd)
+        {
+        // read the empty length
+        source.ReadQuadByte();
+        }
+      }
+    
+    
+    DICOMMapKey ge = (*iter).first;
+    callbackType = VRTypes(((*iter).second.first));
+  
+    if (callbackType != mytype &&
+        mytype != VR_UNKNOWN)
+      {
+      //
+      // mytype is not VR_UNKNOWN if the file is in Explicit format.
+      //
+      callbackType = mytype;
+      }
+ 
+#ifdef DEBUG_DICOM
+    this->DumpTag(this->ParserOutputFile, group, element, callbackType, tempdata, length);
+#endif
+
+    dicom_stl::pair<const DICOMMapKey,DICOMMapValue> p = *iter;
+    DICOMMapValue mv = p.second;
+
+    bool doSwap = (this->ToggleByteSwapImageData ^ source.GetPlatformIsBigEndian()) && callbackType == VR_OW;
+
+    if (group == 0x7FE0 &&
+        element == 0x0010 )
+      {
+      if (doSwap)
+        {
+        DICOMSource::swapShorts((ushort*) tempdata, (ushort*) tempdata, length/sizeof(ushort));
+        }
+      }
+    else
+      {
+      if (source.GetPlatformIsBigEndian() == true)  
+        { 
+        switch (callbackType)
+          {
+          case DICOMParser::VR_OW:
+          case DICOMParser::VR_US:
+          case DICOMParser::VR_SS:
+            DICOMSource::swapShorts((ushort*) tempdata, (ushort*) tempdata, length/sizeof(ushort));
+            break;
+          case DICOMParser::VR_FL:
+          case DICOMParser::VR_FD:
+            break;
+          case DICOMParser::VR_SL:
+          case DICOMParser::VR_UL:
+            DICOMSource::swapLongs((ulong*) tempdata, (ulong*) tempdata, length/sizeof(ulong));
+            break;
+          case DICOMParser::VR_AT:
+            break;
+          default:
+            break;
+          }
+        }
+      }
+
+    dicom_stl::vector<DICOMCallback*> * cbVector = mv.second;
+    for (dicom_stl::vector<DICOMCallback*>::iterator cbiter = cbVector->begin();
+         cbiter != cbVector->end();
+         cbiter++)
+      {
+      (*cbiter)->Execute(this,      // parser
+                       ge.first,  // group
+                       ge.second,  // element
+                       callbackType,  // type
+                       tempdata, // data
+                       length);  // length
+      }
+
+    // If the datatype was a sequence, then recurse down the sequence
+    if (callbackType == DICOMParser::VR_SQ)
+      {
+      this->ParseSequence(tempdata, length);
+      }
+
+    delete [] tempdata;
+    }
+  else
+    {
+    //
+    // Some lengths are negative, but we don't 
+    // want to back up the file pointer.
+    //
+    if (length > 0) 
+      {
+      source.Skip(length);
+      }
+#ifdef DEBUG_DICOM
+    this->DumpTag(this->ParserOutputFile, group, element, mytype, (unsigned char*) "Unread.", length);
+#endif
+    }
+}
+
+void DICOMParser::ParseSequence(unsigned char *buffer, quadbyte len)
+{
+  // dicom_stream::cout << dicom_stream::dec << "ParseSequence(), len = " << len << dicom_stream::endl;
+
+  // Create a DICOM wrapper around the buffer
+  DICOMBuffer DataBuffer(buffer, len);
+
+  doublebyte dataelementtag[2];
+  quadbyte itemLength;
+
+  while (DataBuffer.Tell() < len)
+    {
+    // Read the data element tag.  Should be FFFEE0000
+    dataelementtag[0] = DataBuffer.ReadDoubleByte();
+    dataelementtag[1] = DataBuffer.ReadDoubleByte();
+    
+    if (dataelementtag[0] != 0xfffe || dataelementtag[1] != 0xe000)
+      {
+      dicom_stream::cerr << "DICOMParser:: sequence missing data element tag.  Skipping rest of sequence." << dicom_stream::endl;
+      return;
+      }
+    
+    itemLength = DataBuffer.ReadQuadByte();
+    //dicom_stream::cout << "itemLength = " << dicom_stream::hex << itemLength << dicom_stream::dec << dicom_stream::endl;
+    
+    if (static_cast<unsigned int>(itemLength) == 0xFFFFFFFFul)
+      {
+      // undetermined length.  punt for now
+      dicom_stream::cerr << "DICOMParser:: sequence of undetermined length.  Skipping sequence." << dicom_stream::endl;
+      return;
+      }
+    else
+      {
+      // Get the block of data for this item
+      char *itemValue;
+      itemValue = DataBuffer.ReadAsciiCharArray(itemLength);
+
+      // Wrap this data block into a DICOMBuffer
+      DICOMBuffer tBuffer((unsigned char *)itemValue, itemLength);
+
+      // Parse the DICOMBuffer
+      while (tBuffer.Tell() < itemLength)
+        {
+        doublebyte group=0;
+        doublebyte element=0;
+        DICOMParser::VRTypes datatype = DICOMParser::VR_UNKNOWN;
+        
+        this->ReadNextRecord(tBuffer, group, element, datatype);
+
+        this->Implementation->Groups.push_back(group);
+        this->Implementation->Elements.push_back(element);
+        this->Implementation->Datatypes.push_back(datatype);
+        }
+      
+      delete [] itemValue;
+      }
+    } 
+
+  return;
+  
+}
+
+void DICOMParser::InitTypeMap()
+{
+  DICOMRecord dicom_tags[] = {{0x0002, 0x0002, DICOMParser::VR_UI}, // Media storage SOP class uid
+                              {0x0002, 0x0003, DICOMParser::VR_UI}, // Media storage SOP inst uid
+                              {0x0002, 0x0010, DICOMParser::VR_UI}, // Transfer syntax uid
+                              {0x0002, 0x0012, DICOMParser::VR_UI}, // Implementation class uid
+                              {0x0008, 0x0018, DICOMParser::VR_UI}, // Image UID
+                              {0x0008, 0x0020, DICOMParser::VR_DA}, // Series date
+                              {0x0008, 0x0030, DICOMParser::VR_TM}, // Series time
+                              {0x0008, 0x0060, DICOMParser::VR_SH}, // Modality
+                              {0x0008, 0x0070, DICOMParser::VR_SH}, // Manufacturer
+                              {0x0008, 0x0080, DICOMParser::VR_LO}, // Institution
+                              {0x0008, 0x1060, DICOMParser::VR_SH}, // Physician
+                              {0x0008, 0x1090, DICOMParser::VR_LO}, // Model
+                              {0x0010, 0x0010, DICOMParser::VR_PN}, // Patient name                    
+                              {0x0010, 0x0020, DICOMParser::VR_LO}, // Patient ID
+                              {0x0010, 0x0040, DICOMParser::VR_CS}, // Patient sex                    
+                              {0x0010, 0x1010, DICOMParser::VR_AS}, // Patient age
+                              {0x0018, 0x0050, DICOMParser::VR_FL}, // slice thickness
+                              {0x0018, 0x0060, DICOMParser::VR_FL}, // kV
+                              {0x0018, 0x0088, DICOMParser::VR_FL}, // slice spacing
+                              {0x0018, 0x1100, DICOMParser::VR_SH}, // Recon diameter
+                              {0x0018, 0x1151, DICOMParser::VR_FL}, // mA
+                              {0x0018, 0x1210, DICOMParser::VR_SH}, // Recon kernel
+                              {0x0020, 0x000d, DICOMParser::VR_UI}, // Study UID
+                              {0x0020, 0x000e, DICOMParser::VR_UI}, // Series UID
+                              {0x0020, 0x0013, DICOMParser::VR_IS}, // Image number
+                              {0x0020, 0x0032, DICOMParser::VR_SH}, // Patient position
+                              {0x0020, 0x0037, DICOMParser::VR_SH}, // Patient position cosines
+                              {0x0028, 0x0010, DICOMParser::VR_US}, // Num rows
+                              {0x0028, 0x0011, DICOMParser::VR_US}, // Num cols
+                              {0x0028, 0x0030, DICOMParser::VR_FL}, // pixel spacing
+                              {0x0028, 0x0100, DICOMParser::VR_US}, // Bits allocated
+                              {0x0028, 0x0120, DICOMParser::VR_UL}, // pixel padding
+                              {0x0028, 0x1052, DICOMParser::VR_FL}, // pixel offset
+                              {0x7FE0, 0x0010, DICOMParser::VR_OW}   // pixel data
+  };
+
+
+  int num_tags = sizeof(dicom_tags)/sizeof(DICOMRecord);
+
+  doublebyte group;
+  doublebyte element;
+  VRTypes datatype;
+
+  for (int i = 0; i < num_tags; i++)
+    {
+    group = dicom_tags[i].group;
+    element = dicom_tags[i].element;
+    datatype = (VRTypes) dicom_tags[i].datatype;
+    Implementation->TypeMap.insert(dicom_stl::pair<const DICOMMapKey, DICOMTypeValue>(DICOMMapKey(group, element), datatype));
+    }
+
+}
+
+
+void DICOMParser::SetDICOMTagCallbacks(doublebyte group, doublebyte element, VRTypes datatype, dicom_stl::vector<DICOMCallback*>* cbVector)
+{
+  Implementation->Map.insert(dicom_stl::pair<const DICOMMapKey, DICOMMapValue>(DICOMMapKey(group, element), DICOMMapValue((int)datatype, cbVector)));
+}
+
+
+bool DICOMParser::CheckMagic(char* magic_number) 
+{
+  return (
+          (magic_number[0] == DICOM_MAGIC[0]) &&
+          (magic_number[1] == DICOM_MAGIC[1]) &&
+          (magic_number[2] == DICOM_MAGIC[2]) &&
+          (magic_number[3] == DICOM_MAGIC[3])
+          );
+}
+
+void DICOMParser::DumpTag(dicom_stream::ostream& out, doublebyte group, doublebyte element, VRTypes vrtype, unsigned char* tempdata, quadbyte length)
+{
+
+  int t2 = int((0x0000FF00 & vrtype) >> 8);
+  int t1 = int((0x000000FF & vrtype));
+
+  if (t1 == 0 && t2 == 0)
+    {
+    t1 = '?';
+    t2 = '?';
+    }
+
+  char ct2(t2);
+  char ct1(t1);
+    
+  out << "(0x";
+
+  out.width(4);
+  char prev = out.fill('0');
+
+  out << dicom_stream::hex << group;
+  out << ",0x";
+
+  out.width(4);
+  out.fill('0');
+    
+  out << dicom_stream::hex << element;
+  out << ") ";
+
+  out.fill(prev);
+  out << dicom_stream::dec;
+  out << " " << ct1 << ct2 << " ";
+  out << "[" << length << " bytes] ";
+  
+  if (group == 0x7FE0 && element == 0x0010)
+    {
+    out << "Image data not printed." ;
+    }
+  else if (group == 0x0047 && element == 0x20d1)
+    {
+    out << "Volume segment list not printed.";
+    }
+  else if (group == 0x0047 && element == 0x20d3)
+    {
+    out << "Volume density list not printed.";
+    }
+  else
+    {
+    out << (tempdata ? (char*) tempdata : "NULL");
+    }
+ 
+  out << dicom_stream::dec << dicom_stream::endl;
+  out.fill(prev);
+  out << dicom_stream::dec;
+
+  return;
+
+}
+
+void DICOMParser::ModalityTag(doublebyte, doublebyte, VRTypes, unsigned char* tempdata, quadbyte)
+{
+  if (!strcmp( (char*)tempdata, "MR"))
+    {
+    // this->AddMRTags();
+    }
+  else if (!strcmp((char*) tempdata, "CT"))
+    {
+    }
+  else if (!strcmp((char*) tempdata, "US"))
+    {
+    }
+}
+
+void DICOMParser::AddDICOMTagCallbacks(doublebyte group, doublebyte element, VRTypes datatype, dicom_stl::vector<DICOMCallback*>* cbVector)
+{
+  DICOMParserMap::iterator miter = Implementation->Map.find(DICOMMapKey(group,element));
+  if (miter != Implementation->Map.end())
+    {
+    for (dicom_stl::vector<DICOMCallback*>::iterator iter = cbVector->begin();
+         iter != cbVector->end();
+         iter++)
+      {
+      dicom_stl::vector<DICOMCallback*>* callbacks = (*miter).second.second;
+      callbacks->push_back(*iter);
+      }
+    }
+  else
+    {
+    this->SetDICOMTagCallbacks(group, element, datatype, cbVector);
+    }
+}
+
+void DICOMParser::AddDICOMTagCallback(doublebyte group, doublebyte element, VRTypes datatype, DICOMCallback* cb)
+{
+  DICOMParserMap::iterator miter = Implementation->Map.find(DICOMMapKey(group,element));
+  if (miter != Implementation->Map.end())
+    {
+    dicom_stl::vector<DICOMCallback*>* callbacks = (*miter).second.second;
+    callbacks->push_back(cb);
+    }
+  else
+    {
+    dicom_stl::vector<DICOMCallback*>* callback = new dicom_stl::vector<DICOMCallback*>;
+    callback->push_back(cb);
+    this->SetDICOMTagCallbacks(group, element, datatype, callback);
+    }
+}
+
+void DICOMParser::AddDICOMTagCallbackToAllTags(DICOMCallback* cb)
+{
+  DICOMParserMap::iterator miter;
+  for (miter = Implementation->Map.begin();
+       miter != Implementation->Map.end();
+       miter++);
+  {
+  dicom_stl::vector<DICOMCallback*>* callbacks = (*miter).second.second;
+  callbacks->push_back(cb);
+  }
+}
+
+bool DICOMParser::ParseExplicitRecord(doublebyte, doublebyte, 
+                                      quadbyte& length, 
+                                      VRTypes& represent)
+{
+  doublebyte representation = this->DataFile->ReadDoubleByte();
+
+  bool valid = this->IsValidRepresentation(*this->DataFile, representation, length, represent);
+
+  if (valid)
+    {
+    return true;        
+    }
+  else
+    {
+    represent = VR_UNKNOWN;
+    length = 0;
+    return false;
+    }
+}
+
+bool DICOMParser::ParseImplicitRecord(doublebyte group, doublebyte element,
+                                      quadbyte& length,
+                                      VRTypes& represent)
+{
+  DICOMImplicitTypeMap::iterator iter = 
+    Implementation->TypeMap.find(DICOMMapKey(group,element));
+  represent = VRTypes((*iter).second);
+  //
+  // length?
+  //
+  length = this->DataFile->ReadQuadByte();
+  return false;
+}
+
+
+
+void DICOMParser::TransferSyntaxCallback(DICOMParser *,
+                                         doublebyte,
+                                         doublebyte,
+                                         DICOMParser::VRTypes,
+                                         unsigned char* val,
+                                         quadbyte) 
+
+{
+#ifdef DEBUG_DICOM
+  dicom_stream::cout << "DICOMParser::TransferSyntaxCallback" << dicom_stream::endl;
+#endif
+
+  const char* TRANSFER_UID_EXPLICIT_BIG_ENDIAN = "1.2.840.10008.1.2.2";
+  const char* TRANSFER_UID_GE_PRIVATE_IMPLICIT_BIG_ENDIAN = "1.2.840.113619.5.2";
+
+  // char* fileEndian = "LittleEndian";
+  // char* dataEndian = "LittleEndian";
+
+  this->ToggleByteSwapImageData = false;
+
+  if (strcmp(TRANSFER_UID_EXPLICIT_BIG_ENDIAN, (char*) val) == 0)
+    {
+#ifdef DEBUG_DICOM
+    dicom_stream::cout << "EXPLICIT BIG ENDIAN" << dicom_stream::endl;
+#endif
+    this->ToggleByteSwapImageData = true;
+    //
+    // Data byte order is big endian
+    // 
+    // We're always reading little endian in the beginning,
+    // so now we need to swap.
+    }
+  else if (strcmp(TRANSFER_UID_GE_PRIVATE_IMPLICIT_BIG_ENDIAN, (char*) val) == 0)
+    {
+    this->ToggleByteSwapImageData = true;
+#ifdef DEBUG_DICOM
+    dicom_stream::cout << "GE PRIVATE TRANSFER SYNTAX" << dicom_stream::endl;
+    dicom_stream::cout << "ToggleByteSwapImageData : " << this->ToggleByteSwapImageData << dicom_stream::endl;
+#endif
+    }
+  else
+    {
+    }
+}
+
+void DICOMParser::GetGroupsElementsDatatypes(dicom_stl::vector<doublebyte>& groups,
+                                             dicom_stl::vector<doublebyte>& elements,
+                                             dicom_stl::vector<DICOMParser::VRTypes>& datatypes)
+{
+  groups.clear();
+  elements.clear();
+  datatypes.clear();
+
+  dicom_stl::vector<doublebyte>::iterator giter; // = this->Groups.begin();
+  dicom_stl::vector<doublebyte>::iterator eiter; // = this->Elements.begin();
+  dicom_stl::vector<DICOMParser::VRTypes>::iterator diter; // = this->Datatypes.begin();
+  
+  for (giter = this->Implementation->Groups.begin(), eiter = this->Implementation->Elements.begin(), diter = this->Implementation->Datatypes.begin();
+       giter != this->Implementation->Groups.end(), eiter != this->Implementation->Elements.end(), diter != this->Implementation->Datatypes.end();
+       giter++, eiter++, diter++)
+    {
+    groups.push_back(*giter);
+    elements.push_back(*eiter);
+    datatypes.push_back(*diter);
+    }
+}
+
+void DICOMParser::ClearAllDICOMTagCallbacks()
+{
+  DICOMParserMap::iterator mapIter;
+  
+  for (mapIter = this->Implementation->Map.begin();
+       mapIter != this->Implementation->Map.end();
+       mapIter++)
+       {
+       dicom_stl::pair<const DICOMMapKey, DICOMMapValue> mapPair = *mapIter;
+       DICOMMapValue mapVal = mapPair.second;
+       dicom_stl::vector<DICOMCallback*>* cbVector = mapVal.second;
+       
+       delete cbVector;
+       }
+
+  this->Implementation->Map.clear();
+}
+
+DICOMParser::DICOMParser(const DICOMParser&)
+{
+  dicom_stream::cerr << "DICOMParser copy constructor should not be called!" << dicom_stream::endl;
+}
+
+void DICOMParser::operator=(const DICOMParser&)
+{
+  dicom_stream::cerr << "DICOMParser assignment operator should not be called!" << dicom_stream::endl;
+}
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMParser.h b/Utilities/ITK/Utilities/DICOMParser/DICOMParser.h
new file mode 100644
index 0000000000000000000000000000000000000000..11346115432353ecc10c6cb605ee998b69fd0cc4
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMParser.h
@@ -0,0 +1,279 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMParser.h,v $
+  Language:  C++
+  Date:      $Date: 2004/03/21 21:40:03 $
+  Version:   $Revision: 1.17 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifndef __DICOMParser_h_
+#define __DICOMParser_h_
+
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( disable : 4786 )
+#pragma warning ( disable : 4503 )
+#pragma warning ( disable : 4710 )
+#pragma warning ( disable : 4702 )
+#pragma warning ( push, 3 )
+#endif 
+
+
+#include <map>
+#include <utility> 
+#include <vector>
+
+#include "DICOMConfig.h"
+#include "DICOMFile.h"
+#include "DICOMTypes.h"
+#include "DICOMParserMap.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+class DICOMBuffer;
+class DICOMCallback;
+template <class T> class DICOMMemberCallback;
+
+//DICOM_EXPIMP_TEMPLATE template class DICOM_EXPORT dicom_stl::vector<doublebyte>;
+
+class DICOMParserImplementation;
+
+//
+// We should keep a map with the implicit types for the groups and elements
+// separate from the callbacks.  We can use this for the implicit types.
+//
+//
+
+class DICOM_EXPORT DICOMParser
+{
+ public:
+
+  //
+  // Default constructor
+  //
+  DICOMParser();
+
+  //
+  // Default destructor.
+  //
+  virtual ~DICOMParser();
+
+  //
+  // Opens a file and initializes the parser.
+  //
+  bool OpenFile(const dicom_stl::string& filename);
+
+  //
+  // Return the name of the file last processed.
+  //
+  const dicom_stl::string& GetFileName();
+  
+  //
+  // This method kicks off the parser.
+  // OpenFile needs to be called first.
+  //
+  bool ReadHeader();
+
+  //
+  // This method can kick off the parser on a provided DICOM source
+  // (either a DICOMFile or DICOMBuffer)
+  //
+  bool ReadHeader(DICOMSource &source);
+
+  //
+  // Static method that returns true if a DICOMSource
+  // contains a DICOM image.
+  //
+  static bool IsDICOMFile(DICOMSource &file);
+
+  bool IsDICOMFile()
+    {
+    if (!this->DataFile)
+      {
+      return false;
+      }
+    return DICOMParser::IsDICOMFile(*(this->DataFile));
+    }
+
+  //
+  // Static method that checks the DICOM magic number.
+  //
+  static bool CheckMagic(char* magic_number);
+
+  //
+  // Defined DICOM types.
+  //
+  enum VRTypes 
+    {
+      VR_UNKNOWN = 0x0,
+      VR_OB=0x424f, // Other byte string (string of bytes, insensitive to byte order)
+      VR_AW=0x5741, 
+      VR_AE=0x4541, // Application Entity (char string)
+      VR_AS=0x5341, // Age string (char string)
+      VR_CS=0x5343, // Code string (char string, leading/trailing spaces insignificant)
+      VR_UI=0x4955, // UID (character string)
+      VR_DA=0x4144, // Date (char string)
+      VR_DS=0x5344, // Decimal string (char string representing a fixed/floating pt number)
+      VR_DT=0x5444, // Date Time (char string)
+      VR_IS=0x5349, // Integer string (char string representing an integer)
+      VR_LO=0x4f4c, // Long string (character string padded with leading/trailing spaces)
+      VR_LT=0x544c, // Long text (character string with one or more paragraphs.)
+      VR_OW=0x574f, // Other word string (sensitive to byte order, transfer syntax)
+      VR_PN=0x4e50, // Person name (character string)
+      VR_ST=0x5453, // Short text (character string, one or more paragraphs)
+      VR_TM=0x4d54, // Time (character string)
+      VR_UN=0x4e55,
+      VR_UT=0x5455, // Unlimited text (character string)
+      VR_SQ=0x5153, // Sequence of items
+      VR_SH=0x4853, // Short string (character string with leading/trailing spaces).
+      VR_FL=0x4c46, // Floating point single precision
+      VR_SL=0x4c53, // Signed long, (signed 32bits, 2's complement form.)
+      VR_AT=0x5441, // Attribute tag (ordered pair 16 bit unsigned)
+      VR_UL=0x4c55, // Unsigned long (unsigned 32 bits)
+      VR_US=0x5355, // Unsigned short (unsigned 16 bits)
+      VR_SS=0x5353, // Signed short, (signed 16bits, 2's complement)
+      VR_FD=0x4446  // Floating point double precision
+    };
+
+  //
+  // Callback for the modality tag.
+  //
+  void ModalityTag(doublebyte group, doublebyte element, VRTypes datatype, unsigned char* tempdata, quadbyte length);
+
+  void SetDICOMTagCallbacks(doublebyte group, doublebyte element, VRTypes datatype, dicom_stl::vector<DICOMCallback*>* cbVector);
+  void AddDICOMTagCallbacks(doublebyte group, doublebyte element, VRTypes datatype, dicom_stl::vector<DICOMCallback*>* cbVector);
+  void AddDICOMTagCallback (doublebyte group, doublebyte element, VRTypes datatype, DICOMCallback* cb);
+  void AddDICOMTagCallbackToAllTags(DICOMCallback* cb);
+
+  DICOMFile* GetDICOMFile()
+    {
+    return this->DataFile;
+    }
+
+  void ClearAllDICOMTagCallbacks();
+
+
+  void TransferSyntaxCallback(DICOMParser *parser,
+                              doublebyte,
+                              doublebyte,
+                              DICOMParser::VRTypes,
+                              unsigned char* val,
+                              quadbyte) ;
+
+  void GetGroupsElementsDatatypes(dicom_stl::vector<doublebyte>& groups,
+                                  dicom_stl::vector<doublebyte>& elements,
+                                  dicom_stl::vector<VRTypes>& datatypes);
+
+ protected:
+
+  bool ParseExplicitRecord(doublebyte group, doublebyte element, 
+                           quadbyte& length, 
+                           VRTypes& represent);
+
+  bool ParseImplicitRecord(doublebyte group, doublebyte element,
+                           quadbyte& length,
+                           VRTypes& represent);
+  //
+  // Print a tag.
+  //
+  // void DumpTag(doublebyte group, doublebyte element, VRTypes datatype, unsigned char* data, quadbyte length);
+  void DumpTag(dicom_stream::ostream& out, doublebyte group, doublebyte element, VRTypes vrtype, unsigned char* tempdata, quadbyte length);
+
+  struct DICOMRecord 
+    {
+    doublebyte group;
+    doublebyte element;
+    VRTypes datatype;
+    };
+
+  //
+  // Check to see if the type is a valid DICOM type.  If not, figure
+  // out the right thing to do next (i.e. compute the element length).
+  //
+  bool IsValidRepresentation(DICOMSource &source, doublebyte rep, quadbyte& len, VRTypes &mytype);
+  
+  //
+  // Reads a record.
+  //
+  void ReadNextRecord(DICOMSource &source, doublebyte& group, doublebyte& element, DICOMParser::VRTypes& mytype);
+
+  //
+  // Parse a sequence from a memory block
+  //
+  void ParseSequence(unsigned char *buffer, quadbyte len);
+  
+  //
+  // Sets up the type map.
+  //
+  void InitTypeMap();
+  
+  //
+  // Flags for byte swaping header values and 
+  // image data.
+  // 
+  bool ByteSwap;
+  bool ByteSwapData;
+
+  //
+  // Stores a map from pair<group, element> keys to
+  // values of pair<vector<DICOMCallback*>, datatype>
+  //
+  // DICOMParserMap Map;
+
+  //
+  // Stores a map from pair<group, element> keys to
+  // values of datatype.  We use this to store the 
+  // datatypes for implicit keys that we are 
+  // interested in.
+  //
+  // DICOMImplicitTypeMap TypeMap;
+
+  //
+  // Used for outputting debug information.
+  //
+  dicom_stream::ofstream ParserOutputFile;
+
+  //
+  // Pointer to the DICOMFile we're parsing.
+  //
+  DICOMFile* DataFile;
+  dicom_stl::string FileName;
+  
+  bool ToggleByteSwapImageData;
+
+  //dicom_stl::vector<doublebyte> Groups;
+  //dicom_stl::vector<doublebyte> Elements;
+  //dicom_stl::vector<VRTypes> Datatypes;
+
+  DICOMMemberCallback<DICOMParser>* TransferSyntaxCB;
+
+  //
+  // Implementation contains stl templated classes that 
+  // can't be exported from a DLL in Windows. We hide
+  // them in the implementation to get rid of annoying
+  // compile warnings.
+  //
+  DICOMParserImplementation* Implementation;
+
+ private:
+  DICOMParser(const DICOMParser&);  
+  void operator=(const DICOMParser&); 
+};
+
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
+
+#endif   // __DICOMParser_h_
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMParserMap.h b/Utilities/ITK/Utilities/DICOMParser/DICOMParserMap.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a8eae04b6e67a5b78224b1a595fcfa45467e9c1
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMParserMap.h
@@ -0,0 +1,143 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMParserMap.h,v $
+  Language:  C++
+  Date:      $Date: 2004/03/21 21:40:03 $
+  Version:   $Revision: 1.6 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifndef __DICOM_PARSER_MAP__H_
+#define __DICOM_PARSER_MAP__H_
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( disable : 4786 )
+#pragma warning ( disable : 4503 )
+#pragma warning ( disable : 4710 )
+#pragma warning ( disable : 4702 )
+#pragma warning ( push, 3 )
+#endif 
+
+#include <map>
+#include <utility>
+
+#include "DICOMConfig.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+class DICOMCallback;
+
+//
+// Structure that implements a compare operator for
+// a pair of doublebytes.  This is used when comparing
+// group, element pairs.
+//
+struct group_element_compare 
+{
+  bool operator() (const dicom_stl::pair<doublebyte, doublebyte> p1, const dicom_stl::pair<doublebyte, doublebyte> p2) const
+  {
+    if (p1.first < p2.first)
+      {
+      return true;  
+      }
+    else if (p1.first == p2.first)
+      {
+      if (p1.second < p2.second)
+        {
+        return true;
+        }
+      else
+        {
+        return false;
+        }
+      }
+    else 
+      {
+      return false;
+      }
+  }
+};
+
+//
+// Typedef a pair of doublebytes
+//
+typedef dicom_stl::pair<doublebyte, doublebyte> DICOMMapKeyOverride;
+
+// DICOM_EXPIMP_TEMPLATE template struct DICOM_MAP_EXPORT dicom_stream::pair<doublebyte, doublebyte>;
+//
+// Subclass of a pair of doublebytes to make
+// type names shorter in the code.
+//
+class  DICOMMapKey : public DICOMMapKeyOverride
+{
+ public:
+  DICOMMapKey(doublebyte v1, doublebyte v2) :
+    dicom_stl::pair<doublebyte, doublebyte> (v1, v2)
+  {
+
+  }
+
+};
+
+//
+// Typedef of a pair of doublebyte, vector.
+//
+typedef dicom_stl::pair<doublebyte, dicom_stl::vector<DICOMCallback*>*> DICOMMapValueOverride;
+
+
+// DICOM_EXPIMP_TEMPLATE template struct DICOM_MAP_EXPORT dicom_stream::pair<doublebyte, dicom_stream::vector<DICOMCallback*>*>;
+
+//
+// Subclass of pair doublebyte, vector<DICOMCallback*>.
+// Makes types shorter in the code.
+//
+class  DICOMMapValue : public DICOMMapValueOverride
+{
+ public:
+   DICOMMapValue() : dicom_stl::pair<doublebyte, dicom_stl::vector<DICOMCallback*>*>() {};
+
+  DICOMMapValue(doublebyte v1, dicom_stl::vector<DICOMCallback*> * v2) :
+    dicom_stl::pair<doublebyte, dicom_stl::vector<DICOMCallback*>*>(v1, v2)
+  {
+
+  }
+};
+
+
+// DICOM_EXPIMP_TEMPLATE template class DICOM_MAP_EXPORT dicom_stream::map<DICOMMapKey, DICOMMapValue, group_element_compare>;
+
+//
+// Subclass of the particular map we're using.  Again,
+// makes type specifiers shorter in the code.
+//
+class  DICOMParserMap : 
+  public  dicom_stl::map<DICOMMapKey, DICOMMapValue, group_element_compare> 
+{
+
+};
+
+typedef doublebyte DICOMTypeValue;
+
+// DICOM_EXPIMP_TEMPLATE template class  dicom_stream::map<DICOMMapKey, DICOMTypeValue, group_element_compare>;
+
+class  DICOMImplicitTypeMap : 
+  public dicom_stl::map<DICOMMapKey, DICOMTypeValue, group_element_compare>
+{
+
+};
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif 
+
+#endif
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMSource.cxx b/Utilities/ITK/Utilities/DICOMParser/DICOMSource.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d206f4127d149047ef8b64fbd0e12c4ff347ba59
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMSource.cxx
@@ -0,0 +1,216 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMSource.cxx,v $
+  Language:  C++
+  Date:      $Date: 2004/03/21 21:40:03 $
+  Version:   $Revision: 1.2 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( disable : 4710 )
+#pragma warning ( push, 3 )
+#endif 
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <stdio.h>
+#include <string>
+
+#include "DICOMConfig.h"
+#include "DICOMSource.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+DICOMSource::DICOMSource() 
+{
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  PlatformIsBigEndian = (u.c[sizeof (long) - 1] == 1);
+  if (PlatformIsBigEndian)
+    {
+    PlatformEndian = "BigEndian";
+    }
+  else
+    {
+    PlatformEndian = "LittleEndian";
+    }
+}
+
+DICOMSource::~DICOMSource()
+{
+}
+
+DICOMSource::DICOMSource(const DICOMSource& in)
+{
+  if (strcmp(in.PlatformEndian, "LittleEndian") == 0)
+    {
+    PlatformEndian = "LittleEndian";
+    }
+  else
+    {
+    PlatformEndian = "BigEndian";
+    }
+}
+
+void DICOMSource::operator=(const DICOMSource& in)
+{
+  if (strcmp(in.PlatformEndian, "LittleEndian") == 0)
+    {
+    PlatformEndian = "LittleEndian";
+    }
+  else
+    {
+    PlatformEndian = "BigEndian";
+    }
+}
+
+doublebyte DICOMSource::ReadDoubleByte() 
+{
+  doublebyte sh = 0;
+  int sz = sizeof(doublebyte);
+  this->Read((char*)&(sh),sz); 
+  if (PlatformIsBigEndian) 
+    {
+    sh = swapShort(sh);
+    }
+  return(sh);
+}
+
+doublebyte DICOMSource::ReadDoubleByteAsLittleEndian() 
+{
+  doublebyte sh = 0;
+  int sz = sizeof(doublebyte);
+  this->Read((char*)&(sh),sz); 
+  if (PlatformIsBigEndian)
+    {
+    sh = swapShort(sh);
+    }
+  return(sh);
+}
+
+quadbyte DICOMSource::ReadQuadByte() 
+{
+  quadbyte sh;
+  int sz = sizeof(quadbyte);
+  this->Read((char*)&(sh),sz);
+  if (PlatformIsBigEndian) 
+    {
+    sh = swapLong(sh);
+    }
+  return(sh);
+}
+
+quadbyte DICOMSource::ReadNBytes(int len) 
+{
+  quadbyte ret = -1;
+  switch (len) 
+    {
+    case 1:
+      char ch;
+      this->Read(&ch,1);  //from Image
+      ret =(quadbyte) ch;
+      break;
+    case 2:
+      ret =(quadbyte) ReadDoubleByte();
+      break;
+    case 4:
+      ret = ReadQuadByte();
+      break;
+    default:
+      dicom_stream::cerr << "Unable to read " << len << " bytes" << dicom_stream::endl;
+      break;
+    }
+  return (ret);
+}
+
+float DICOMSource::ReadAsciiFloat(int len) 
+{
+  float ret=0.0;
+
+
+  char* val = new char[len+1];
+  this->Read(val,len);
+  val[len] = '\0';
+
+#if 0
+  //
+  // istrstream destroys the data during formatted input.
+  //
+  int len2 = static_cast<int> (strlen((char*) val));
+  char* val2 = new char[len2];
+  strncpy(val2, (char*) val, len2);
+
+  dicom_stream::istrstream data(val2);
+  data >> ret;
+  delete [] val2;
+#else
+  sscanf(val,"%e",&ret);
+#endif
+
+  // dicom_stream::cout << "Read ASCII float: " << ret << dicom_stream::endl;
+
+  delete [] val;
+  return (ret);
+}
+
+int DICOMSource::ReadAsciiInt(int len) 
+{
+  int ret=0;
+
+  char* val = new char[len+1];
+  this->Read(val,len);
+  val[len] = '\0';
+
+#if 0
+  //
+  // istrstream destroys the data during formatted input.
+  //
+  int len2 = static_cast<int> (strlen((char*) val));
+  char* val2 = new char[len2];
+  strncpy(val2, (char*) val, len2);
+
+  dicom_stream::istrstream data(val2);
+  data >> ret;
+  delete [] val2;
+#else
+  sscanf(val,"%d",&ret);
+#endif
+
+  // dicom_stream::cout << "Read ASCII int: " << ret << dicom_stream::endl;
+
+  delete [] val;
+  return (ret);
+}
+
+char* DICOMSource::ReadAsciiCharArray(int len) 
+{
+  if (len <= 0)
+    {
+    return NULL;
+    }
+  char* val = new char[len + 1];
+  this->Read(val, len);
+  val[len] = 0; // NULL terminate.
+  return val;
+}
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMSource.h b/Utilities/ITK/Utilities/DICOMParser/DICOMSource.h
new file mode 100644
index 0000000000000000000000000000000000000000..caf82c7164e8ca28d6c423604b783ffc98641c7a
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMSource.h
@@ -0,0 +1,235 @@
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMSource.h,v $
+  Language:  C++
+  Date:      $Date: 2004/11/10 19:22:13 $
+  Version:   $Revision: 1.3 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#ifndef __DICOMSOURCE_H_
+#define __DICOMSOURCE_H_
+
+#ifdef _MSC_VER
+#pragma warning ( disable : 4514 )
+#pragma warning ( push, 3 )
+#endif 
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "DICOMTypes.h"
+#include "DICOMConfig.h"
+
+namespace DICOMPARSER_NAMESPACE
+{
+//
+// Abstraction of a DICOM data source used by the DICOMParser.
+//
+class DICOM_EXPORT DICOMSource 
+{
+ public:
+  DICOMSource();
+  virtual ~DICOMSource();
+  
+  //
+  // Return the position in the source
+  //
+  virtual long Tell()=0;
+  
+  // 
+  // Move to a particular position in the source.
+  //
+  virtual void SkipToPos(long)=0;
+  
+  //
+  // Return the size of the source.
+  //
+  virtual long GetSize()=0;
+  
+  //
+  // Skip a number of bytes.
+  // 
+  virtual void Skip(long)=0;
+  
+  //
+  // Skip to the beginning of the source.
+  //
+  virtual void SkipToStart()=0;
+  
+  //
+  // Read data of length len.
+  //
+  virtual void Read(void* data, long len)=0;
+  
+  //
+  // Read a double byte of data.
+  //
+  virtual doublebyte ReadDoubleByte();
+  virtual doublebyte ReadDoubleByteAsLittleEndian();
+
+  //
+  // Read a quadbyte of data.
+  //
+  virtual quadbyte   ReadQuadByte();
+  
+  //
+  // Read nbytes of data up to 4 bytes.
+  //
+  virtual quadbyte   ReadNBytes(int len);
+  
+  // 
+  // Read a float an ascii.
+  //
+  virtual float      ReadAsciiFloat(int len);
+  
+  //
+  // Read an int as ascii.
+  //
+  virtual int        ReadAsciiInt(int len);
+  
+  //
+  // Read an array of ascii characters.
+  //
+  virtual char*      ReadAsciiCharArray(int len);
+  
+  //
+  // Convert the data to signed long.
+  //
+  static long ReturnAsSignedLong(unsigned char* data, bool )
+  {
+    return *((quadbyte*) data);
+  }
+  
+  
+  //
+  // Convert the data to unsigned long.
+  //
+  static ulong ReturnAsUnsignedLong(unsigned char* data, bool )
+  {
+    return *((ulong*) data);
+  }
+  
+  //
+  // Convert data to unsigned short.
+  //
+  static ushort ReturnAsUnsignedShort(unsigned char* data, bool )
+  {
+    return *((doublebyte*)data);
+  }
+  
+  //
+  // Convert data to signed short.
+  // 
+  static short int ReturnAsSignedShort(unsigned char* data, bool )
+  {
+    return *((short int*)data);
+  }
+
+  //
+  // Convert data to int.
+  //
+  static int ReturnAsInteger(unsigned char* data, bool)
+  {
+    return static_cast<int> (atoi((const char *)data));
+  }
+  
+  static float ReturnAsFloat(unsigned char* data, bool)
+    {
+    return static_cast<float> (atof((const char *)data));
+    }
+
+  bool GetPlatformIsBigEndian()
+    {
+    return PlatformIsBigEndian;
+    }
+
+  void SetPlatformIsBigEndian(bool v)
+    {
+    this->PlatformIsBigEndian = v;
+    }
+
+  //
+  // Swap the bytes in an array of unsigned shorts.
+  //
+  static void swapShorts(ushort *ip, ushort *op, int count)
+  {
+    while (count)
+      {
+      *op++ = swapShort(*ip++);
+      count--;
+      }
+  }
+  
+  //
+  // Swap the bytes in an array of unsigned longs.
+  //
+  static void swapLongs(ulong *ip, ulong *op, int count)
+  {
+    while (count)
+      {
+      *op++ = swapLong(*ip++);
+      count--;
+      }
+  }
+  
+  
+  //
+  // Swap the bytes in an unsigned short.
+  //
+  static ushort swapShort(ushort v)
+  {
+    return ushort((v << 8)
+      | (v >> 8));
+  }
+  
+  // 
+  // Swap the bytes in an unsigned long.
+  //
+  static ulong swapLong(ulong v)
+    {
+    return ulong((v << 24) 
+      | (v << 8) & 0x00ff0000
+      | (v >> 8) & 0x0000ff00
+      | (v >> 24));
+    }
+
+  const char* GetPlatformEndian() {return this->PlatformEndian;}
+
+ protected:
+  DICOMSource(const DICOMSource&);
+  void operator=(const DICOMSource&);  
+
+  //
+  // Flag for swaping bytes.
+  //
+  bool PlatformIsBigEndian;
+
+  //
+  // Platform endianness
+  //
+  const char* PlatformEndian;
+
+ private:
+
+};
+}
+#ifdef _MSC_VER
+#pragma warning ( pop )
+#endif
+
+#endif // __DICOMSOURCE_H_
+
+
diff --git a/Utilities/ITK/Utilities/DICOMParser/DICOMTypes.h b/Utilities/ITK/Utilities/DICOMParser/DICOMTypes.h
new file mode 100644
index 0000000000000000000000000000000000000000..c32002061418e4646377dbdb093107950d0aeb91
--- /dev/null
+++ b/Utilities/ITK/Utilities/DICOMParser/DICOMTypes.h
@@ -0,0 +1,30 @@
+
+/*=========================================================================
+
+  Program:   DICOMParser
+  Module:    $RCSfile: DICOMTypes.h,v $
+  Language:  C++
+  Date:      $Date: 2003/10/23 17:57:35 $
+  Version:   $Revision: 1.4 $
+
+  Copyright (c) 2003 Matt Turek
+  All rights reserved.
+  See Copyright.txt for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even 
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+
+#ifndef __DICOM_TYPES_H_
+#define __DICOM_TYPES_H_
+
+typedef unsigned short doublebyte;
+typedef int quadbyte;
+typedef unsigned short ushort;
+typedef unsigned long  ulong;
+
+
+#endif
diff --git a/Utilities/ITK/Utilities/Dart/AllowContinuous.bat.in b/Utilities/ITK/Utilities/Dart/AllowContinuous.bat.in
new file mode 100644
index 0000000000000000000000000000000000000000..05e90f2e7722419801fc7fcaa60596d4f4454323
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/AllowContinuous.bat.in
@@ -0,0 +1,11 @@
+rem
+rem Allow Continuous to run
+rem
+c:
+
+cd @ITK_BINARY_DIR@
+if EXIST continuous.lock (
+  del continuous.lock
+)
+
+
diff --git a/Utilities/ITK/Utilities/Dart/AllowContinuous.sh.in b/Utilities/ITK/Utilities/Dart/AllowContinuous.sh.in
new file mode 100644
index 0000000000000000000000000000000000000000..1798e703e974cc32d9476832f93e1f2506010ca0
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/AllowContinuous.sh.in
@@ -0,0 +1,6 @@
+#!/bin/sh
+echo "Allow Continuous to run"
+cd @ITK_BINARY_DIR@
+if [ -e continuous.lock ]
+then  rm continuous.lock;
+fi
diff --git a/Utilities/ITK/Utilities/Dart/BuildContinuous.bat.in b/Utilities/ITK/Utilities/Dart/BuildContinuous.bat.in
new file mode 100644
index 0000000000000000000000000000000000000000..8ede24ab502f2423de9b8652b8682de6a04d9f06
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/BuildContinuous.bat.in
@@ -0,0 +1,13 @@
+rem
+rem Do a Build Continuously
+rem
+cd @ITK_BINARY_DIR@
+if EXIST continuous.lock (
+  exit /B
+) else (
+  date /T > continuous.lock
+  time /T >> continuous.lock
+  "@TCL_TCLSH@" "@DART_ROOT@/Source/Client/DashboardManager.tcl" "@ITK_BINARY_DIR@/DartConfiguration.tcl" Continuous Start Update Configure Build Test Submit
+  del continuous.lock
+)
+
diff --git a/Utilities/ITK/Utilities/Dart/BuildContinuous.sh.in b/Utilities/ITK/Utilities/Dart/BuildContinuous.sh.in
new file mode 100644
index 0000000000000000000000000000000000000000..1af30f1178a92ea20c859a24cd6dd34d3333448a
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/BuildContinuous.sh.in
@@ -0,0 +1,11 @@
+#!/bin/sh
+echo "Do a Build Continuously"
+cd @ITK_BINARY_DIR@
+if [ -e continuous.lock ]
+then exit;
+else
+date >continuous.lock
+"@TCL_TCLSH@" "@DART_ROOT@/Source/Client/DashboardManager.tcl" DartConfiguration.tcl Continuous Start Update Configure Build Test Submit 2>&1 > "@ITK_BINARY_DIR@/Testing/Continuous.log"
+rm continuous.lock
+rm -f @ITK_BINARY_DIR@/Testing/Temporary/*
+fi
diff --git a/Utilities/ITK/Utilities/Dart/BuildHeaderTest.tcl b/Utilities/ITK/Utilities/Dart/BuildHeaderTest.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..02f5c3281beecd5e7af6d131da8c582979d8fb39
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/BuildHeaderTest.tcl
@@ -0,0 +1,126 @@
+# =========================================================================
+# 
+#   Program:   Insight Segmentation & Registration Toolkit
+#   Module:    $RCSfile: BuildHeaderTest.tcl,v $
+#   Language:  Tcl
+#   Date:      $Date: 2002/12/13 12:48:51 $
+#   Version:   $Revision: 1.6 $
+# 
+
+# Copyright (c) 2001 Insight Consortium
+# All rights reserved.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+
+#  * Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+
+#  * Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+
+#  * The name of the Insight Consortium, nor the names of any consortium members,
+#    nor of any contributors, may be used to endorse or promote products derived
+#    from this software without specific prior written permission.
+
+#   * Modified source versions must be plainly marked as such, and must not be
+#     misrepresented as being the original software.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+set Header {/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit (ITK)
+  Module:
+  Language:  C++
+  Date:
+  Version:
+
+
+Copyright (c) 2000 National Library of Medicine
+All rights reserved.
+
+See COPYRIGHT.txt for copyright details.
+
+=========================================================================*/
+#if defined(_MSC_VER)
+#pragma warning ( disable : 4786 )
+#endif
+
+#include <iostream>
+// This file has been generated by BuildHeaderTest.tcl
+// Test to include each header file for Insight
+}
+
+set Trailer "
+int main ( int , char* [] )
+{
+  
+  return 0;
+}
+"
+
+set D [lsort [glob -nocomplain Code/*]]
+set Directories ""
+foreach d $D \
+{
+  if { [file tail $d] != "CVS" && [file isdirectory $d]} \
+  {
+    lappend Directories [file tail $d]
+  }
+}
+
+foreach Directory $Directories \
+{
+  if { ![file exists [file join Testing Code $Directory]] } \
+  {
+    continue
+  }
+  set f [open [file join Testing Code $Directory itk${Directory}HeaderTest.cxx] w]
+  puts $f $Header
+  foreach File [lsort [glob -nocomplain [file join Code $Directory *.h]]] \
+  {
+      if {[file tail $File] == "itkTestMain.h"} {
+	  continue;
+      }
+      if {[file tail $File] == "itkWindows.h"} {
+	  continue;
+      }
+      if {[file tail $File] == "itkWin32Header.h"} {
+	  continue;
+      }
+      if {[file tail $File] == "itkWin32OutputWindow.h"} {
+	  continue;
+      }
+      if {[file tail $File] == "itkImageViewerWindow.h"} {
+	  continue;
+      }
+#
+# include the .h if there is no .txx
+# otherwise include the .txx
+#
+      set txxFile "[file rootname $File].txx"
+      if {[file tail $txxFile] == "itkImageViewer.txx"} {
+	  continue;
+      }
+      if { [file exists $txxFile] } {
+          puts $f "#include \"[file tail $txxFile]\""
+      } else {
+        puts $f "#include \"[file tail $File]\""
+      }
+  }
+  puts $f $Trailer
+  close $f
+}
+
diff --git a/Utilities/ITK/Utilities/Dart/CMakeLists.txt b/Utilities/ITK/Utilities/Dart/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ad8a2ba34bad1bf0eb4972cc51e8166f60b42ee4
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/CMakeLists.txt
@@ -0,0 +1,54 @@
+IF(WIN32)
+  IF(NOT MINGW)
+  CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/AllowContinuous.bat.in
+                 ${ITK_BINARY_DIR}/AllowContinuous.bat)
+  CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/PreventContinuous.bat.in
+                 ${ITK_BINARY_DIR}/PreventContinuous.bat)
+  CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/BuildContinuous.bat.in
+                 ${ITK_BINARY_DIR}/BuildContinuous.bat)
+  ELSE(NOT MINGW)
+    CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/BuildContinuous.sh.in
+                   ${ITK_BINARY_DIR}/BuildContinuous.sh
+                   @ONLY IMMEDIATE)
+    EXEC_PROGRAM(chmod ARGS 755 \"${ITK_BINARY_DIR}/BuildContinuous.sh\"
+                       OUTPUT_VARIABLE ITK_EXEC_PLEASE_BE_QUIET)
+    CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/AllowContinuous.sh.in
+                   ${ITK_BINARY_DIR}/AllowContinuous.sh
+                   @ONLY IMMEDIATE)
+    EXEC_PROGRAM(chmod ARGS 755 \"${ITK_BINARY_DIR}/AllowContinuous.sh\"
+                       OUTPUT_VARIABLE ITK_EXEC_PLEASE_BE_QUIET)
+    CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/PreventContinuous.sh.in
+                   ${ITK_BINARY_DIR}/PreventContinuous.sh
+                   @ONLY IMMEDIATE)
+    EXEC_PROGRAM(chmod ARGS 755 \"${ITK_BINARY_DIR}/PreventContinuous.sh\"
+                       OUTPUT_VARIABLE ITK_EXEC_PLEASE_BE_QUIET)
+    CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/cronentry.in
+                   ${ITK_BINARY_DIR}/cronentry
+                   @ONLY IMMEDIATE)
+  ENDIF(NOT MINGW)
+ENDIF(WIN32)
+IF(UNIX)
+  CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/BuildContinuous.sh.in
+                 ${ITK_BINARY_DIR}/BuildContinuous.sh
+                 @ONLY IMMEDIATE)
+  EXEC_PROGRAM(chmod ARGS 755 \"${ITK_BINARY_DIR}/BuildContinuous.sh\"
+                     OUTPUT_VARIABLE ITK_EXEC_PLEASE_BE_QUIET)
+  CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/AllowContinuous.sh.in
+                 ${ITK_BINARY_DIR}/AllowContinuous.sh
+                 @ONLY IMMEDIATE)
+  EXEC_PROGRAM(chmod ARGS 755 \"${ITK_BINARY_DIR}/AllowContinuous.sh\"
+                     OUTPUT_VARIABLE ITK_EXEC_PLEASE_BE_QUIET)
+  CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/PreventContinuous.sh.in
+                 ${ITK_BINARY_DIR}/PreventContinuous.sh
+                 @ONLY IMMEDIATE)
+  EXEC_PROGRAM(chmod ARGS 755 \"${ITK_BINARY_DIR}/PreventContinuous.sh\"
+                     OUTPUT_VARIABLE ITK_EXEC_PLEASE_BE_QUIET)
+  CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/cronentry.in
+                 ${ITK_BINARY_DIR}/cronentry
+                 @ONLY IMMEDIATE)
+  CONFIGURE_FILE(${ITK_SOURCE_DIR}/Utilities/Dart/NewSince.csh.in
+                 ${ITK_BINARY_DIR}/NewSince.csh
+                 @ONLY IMMEDIATE)
+  EXEC_PROGRAM(chmod ARGS 755 \"${ITK_BINARY_DIR}/NewSince.csh\"
+                 OUTPUT_VARIABLE ITK_EXEC_PLEASE_BE_QUIET)
+ENDIF(UNIX)
diff --git a/Utilities/ITK/Utilities/Dart/NewSince.csh.in b/Utilities/ITK/Utilities/Dart/NewSince.csh.in
new file mode 100644
index 0000000000000000000000000000000000000000..616701e70be30cf54369521b2450b35bcc498978
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/NewSince.csh.in
@@ -0,0 +1,113 @@
+#! /bin/tcsh -f
+#
+# Find all new files between two dates
+# Usage: NewSince.csh StartDate EndDate
+#
+
+if ($#argv != 2) then
+    echo "Usage: NewSince.csh StartDate EndDate"
+    exit (1)
+endif
+
+echo "Changes from $1 to $2"
+
+set FROM="$1"
+set TO="$2"
+
+set TEMPDIR=@ITK_BINARY_DIR@/Testing/Temporary
+
+(cd @ITK_SOURCE_DIR@; cvs log -d"$FROM<$TO" >${TEMPDIR}/$$.allchanges)
+
+gawk -f @ITK_SOURCE_DIR@/Utilities/Dart/NewSince.gawk ${TEMPDIR}/$$.allchanges | cut -d"/" -f5- >${TEMPDIR}/$$.newandremoved
+
+#
+# remove files in the Attic
+#
+grep -v Attic ${TEMPDIR}/$$.newandremoved >${TEMPDIR}/$$.new
+
+echo "This release covers the period ${FROM} through ${TO}" > ${TEMPDIR}/$$.wikitemp
+echo "== New Classes in this Release ==" >> ${TEMPDIR}/$$.wikitemp
+echo "<pre>" >> ${TEMPDIR}/$$.wikitemp
+grep "^Code/Algorithms" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Code/BasicFilters" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Code/Common" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Code/IO" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Code/Numerics/itk" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Code/Numerics/NeuralNetworks" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Code/Numerics/Statistics" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Code/SpatialObject" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Code/Patented" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "</pre>" >> ${TEMPDIR}/$$.wikitemp
+
+echo "== New Tests in this Release =="  >> ${TEMPDIR}/$$.wikitemp
+echo "<pre>" >> ${TEMPDIR}/$$.wikitemp
+grep "^Testing/Code/Common" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Testing/Code/BasicFilters" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Testing/Code/IO" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Testing/Code/Algorithms" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Testing/Code/Numerics" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Testing/Code/SpatialObject" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Testing/Code/Patented" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "</pre>" >> ${TEMPDIR}/$$.wikitemp
+
+echo "== New Examples in this Release ==" >> ${TEMPDIR}/$$.wikitemp
+echo "<pre>" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/DataRepresentation" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Filtering" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/GUI" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Infrastructure" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Installation" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/IO" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Iterators" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Numerics" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Patented" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Registration" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Segmentations" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/SpatialObjects" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Statistics" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Visualization" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "" >> ${TEMPDIR}/$$.wikitemp
+grep "^Examples/Wrapping" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "</pre>" >> ${TEMPDIR}/$$.wikitemp
+
+echo "== New Utilities in this Release ==" >> ${TEMPDIR}/$$.wikitemp
+echo "<pre>" >> ${TEMPDIR}/$$.wikitemp
+grep "^Utilities/" ${TEMPDIR}/$$.new | sort | uniq >> ${TEMPDIR}/$$.wikitemp
+echo "</pre>" >> ${TEMPDIR}/$$.wikitemp
+
+#
+# remove consecutive blank lines
+#
+cat -s ${TEMPDIR}/$$.wikitemp > ${TEMPDIR}/NewSince.txt
+echo "A Wiki-compatible list of new files is in ${TEMPDIR}/NewSince.txt"
+#
+# cleanup
+#
+rm -f ${TEMPDIR}/$$.*
diff --git a/Utilities/ITK/Utilities/Dart/NewSince.gawk b/Utilities/ITK/Utilities/Dart/NewSince.gawk
new file mode 100644
index 0000000000000000000000000000000000000000..9e382fce2aa63c72ca35250f2270cc9cb3f6255e
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/NewSince.gawk
@@ -0,0 +1,8 @@
+/^RCS file/ {lastFile = $3}
+/revision 1\.1$/ {
+        gsub(",v$","",lastFile);
+        gsub(".cxx$","",lastFile);
+        gsub(".txx$","",lastFile);
+        gsub(".c$","",lastFile);
+        gsub(".h$","",lastFile);
+        printf "new: %s\n", lastFile}
diff --git a/Utilities/ITK/Utilities/Dart/PreventContinuous.bat.in b/Utilities/ITK/Utilities/Dart/PreventContinuous.bat.in
new file mode 100644
index 0000000000000000000000000000000000000000..86900c43eaf6bdde031d6ac5ba6989f524641041
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/PreventContinuous.bat.in
@@ -0,0 +1,11 @@
+rem
+rem Prevent the Continuous
+rem
+c:
+
+cd @ITK_BINARY_DIR@
+if EXIST continuous.lock (
+  exit /B
+) else (
+  echo "Locked by PreventContinuous.bat, probably for nightly" > continuous.lock
+)
diff --git a/Utilities/ITK/Utilities/Dart/PreventContinuous.sh.in b/Utilities/ITK/Utilities/Dart/PreventContinuous.sh.in
new file mode 100644
index 0000000000000000000000000000000000000000..730b2b923e24309617f9f99c2d14fe66b8f4f65f
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/PreventContinuous.sh.in
@@ -0,0 +1,7 @@
+#!/bin/sh
+echo "Prevent Continuous from running"
+cd @ITK_BINARY_DIR@
+if [ -e continuous.lock ]
+then  exit
+fi
+echo "Locked by PreventContinuous.sh, probably for nightly" > continuous.lock
diff --git a/Utilities/ITK/Utilities/Dart/PrintSelfCheck.tcl b/Utilities/ITK/Utilities/Dart/PrintSelfCheck.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ade29a0aaaec623d9389d08cf98c093fffcc2713
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/PrintSelfCheck.tcl
@@ -0,0 +1,687 @@
+#
+# Verify that each class's PrintSelf prints all ivars that have
+# a set/get.
+#
+#
+# Verbose Levels:
+#
+#	0:	No extra printing
+#	1:	Print basic extra information
+#	2:	Print lots of details
+#
+set verbose 0
+
+set class_name ""
+
+set class_count 0
+set class_print_count 0
+set printself_miss_count 0
+set super_miss_count 0
+set ivar_count 0
+set ivar_miss_count 0
+
+set total_class_count 0
+set total_class_print_count 0
+set total_ivar_count 0
+set total_printself_miss_count 0
+set total_super_miss_count 0
+set total_ivar_miss_count 0
+
+# Fileid for the PrintSelfDetails.html file
+set pd_id 0
+
+#
+# class_list contains the following for each class evaluated:
+#
+#  <class>.p		   <true|false> True if printself declared
+#  <class>.s.<super_class> <true|false> True if superclass used in printself
+#  <class>.i.<ivar>	   <true|false> True if ivar used in printself
+
+set class_list(null) 1
+
+proc list_contains { string } {
+
+  global class_list
+
+  set ivar_found 0
+  set searchid [array startsearch class_list]
+
+  while { [array anymore class_list $searchid] } {
+    set element [array nextelement class_list $searchid]
+    if { $element == $string } {
+      set ivar_found 1
+    }
+  }
+
+  array donesearch class_list $searchid
+
+  return $ivar_found
+}
+
+proc get_ivar { string } {
+
+  global verbose
+
+  set ivar_string "-1"
+
+#puts "Getting ivar from macro: $string"
+
+  # Search for the first occurrence of an open parenthesis
+  set first [string first "(" $string];
+
+  if { $first > -1 } {
+
+    set begintrim [string range $string [expr $first + 1] end];
+    set begintrim [string trim $begintrim];
+
+    # Find the end of the ivar
+    set last [string wordend $begintrim 0]
+
+    if { $last > -1 } {
+
+      set ivar_string [string range $begintrim 0 [expr $last - 1] ];
+
+      set ivar_string [string trim $ivar_string];
+
+      if { $verbose >= 2 } {
+        puts "    Macro: $ivar_string"
+      }
+    } 
+  }
+
+  return [string trim $ivar_string]
+}
+
+proc check_header_file { filename } {
+
+  global class_name
+  global class_count
+  global ivar_count
+  global class_list
+  global verbose
+
+  if { $verbose >= 2 } {
+    puts "Processing file: $filename"
+  }
+
+  set data ""
+  set class_name ""
+
+  set printself_found 0
+  set class_found 0
+
+  if { [file readable $filename] } {
+    set fileid [open $filename "r"]
+
+    set private_not_found 1
+
+    #
+    # Read each line in the file
+    #
+    while { [gets $fileid data] >= 0 && $private_not_found } {
+
+      # Search for the printSelf string
+      if { [string match "*PrintSelf*(*" $data] == 1 } {
+        set printself_found 1
+        set class_list($class_name.p) 1
+      }
+
+      if { [string match "*private:*" $data] == 1 } {
+        set private_not_found 0
+      }
+
+      # Search for the class string
+      # Extract the class name from the string
+      if { [string match "*class *_EXPORT*" $data] == 1 } {
+          while { [gets $fileid rest] >= 0 && [string first "\{" $rest] == -1 } {
+          lappend data $rest
+          }
+          set data [join $data]
+        set class_found 1
+
+        set class_ivar_count 0
+
+        set first [string first "_EXPORT" $data];
+        incr first 7
+        if { $first > -1 } {
+
+          set end [expr [string first ":" $data] - 1];
+
+          set newstring [string range $data $first $end ]
+          set class_name [string trim [string trimleft $newstring]];
+        } 
+
+        set class_list($class_name.p) 0
+
+        if { $verbose >= 2 } {
+          puts "    Class Name: $class_name"
+        }
+
+        set first [string first "public" $data]
+        if { $first > -1 } {
+          set first [expr $first + 7];
+          set end [ string length $data]
+
+          set string [string range $data $first $end ]
+
+          set first [string first "itk" $string]
+          set end [string wordend $string $first]
+
+          set super_class [string range $string $first $end ]
+          set super_class [string trim $super_class]
+
+          set class_list($class_name.s.Superclass) 0
+        }
+      }
+
+      if { $class_found == 1 } {
+
+        # Search for Set and Get macros
+        set set_macro_found [string match "*itkSet*Macro*(*" $data]
+        set get_static_const_macro_found [string match "*itkGetStaticConstMacro*(*" $data]
+        set get_macro_found [string match "*itkGet*Macro*(*" $data]
+
+        if { !$get_static_const_macro_found && ( $set_macro_found || $get_macro_found  ) } {
+
+          # Get the ivar from the Macro declaration
+          set ivar [get_ivar $data];
+
+          if { [string compare $ivar "-1"] != 0 } {
+            if { [list_contains "$class_name.i.$ivar"] == 0 } {
+
+              incr ivar_count
+              incr class_ivar_count
+
+              set class_list($class_name.i.$ivar) 0
+            }
+          }
+        } 
+      }
+    } 
+
+    # If a class was found within the file then increment the class count
+    if { $class_found } {
+      incr class_count
+    }
+
+    close $fileid
+
+  }
+
+}
+
+proc check_printself { filename } {
+
+  global verbose
+
+  global class_list
+  global class_name
+
+  if { $verbose >= 2 } {
+    puts "    Checking PrintSelf in file: $filename"
+  }
+
+  if { [file readable $filename] } {
+
+    set fileid [open $filename "r"]
+
+    set search_state 0
+
+    set curly_open 0
+    set curly_close 0
+
+    set line_count 0
+
+    #
+    # Read each line in the file
+    #
+    while { [gets $fileid data] >= 0 && $search_state != 3 } {
+
+      incr line_count
+
+      # Search for the PrintSelf string
+      if { $search_state == 0 && [string match "*PrintSelf*(*" $data] == 1 } {
+        set search_state 1
+        set first [string first ")" $data]
+        set data [string range $data [expr $first + 1] end]
+      }
+
+      # Find the first open curly bracket
+      if { $search_state == 1 } {
+        while { [string length $data] > 0 && $curly_open == 0 } {
+          # Check for an open curly bracket
+          set curly_found [string first "\{" $data]
+          if { $curly_found > -1 } {
+            set data [string range $data [expr $curly_found + 1] end ]
+            set curly_open 1
+            set search_state 2
+          } else {
+            set data ""
+          }
+        }
+      }
+
+      # Count curly brackets in PrintSelf() method and find ivars
+      if { $search_state == 2 } {
+
+        set start 0
+        set end [string length $data]
+        if { [string match "*::PrintSelf(*)*" $data] == 1 } {
+          set start [string first "itk" $data]
+          set end [string wordend $data $start]
+
+          set super_class [string range $data $start [expr $end -1]]
+          set super_class [string trim $super_class]
+
+          if { [list_contains "$class_name.s.Superclass"] == 1 } {
+            set class_list($class_name.s.Superclass) 1
+          } elseif { $verbose >= 2 } {
+            puts "\tSuperclass Issue:\tCan't find $class_name.s.$super_class"
+          }
+        }
+
+        while { $start < $end && $curly_open > $curly_close } {
+          set word_end [string wordend $data $start]
+          set token [string range $data $start [expr $word_end -1] ]
+          set token [string trim $token]
+          set start $word_end
+	  if { $verbose >= 2 } {
+	    puts "\tNew Token: $token"
+	  }
+
+          # Check for open and close curly braces
+          if { [string compare "\{" $token] == 0 } {
+            incr curly_open 
+          } elseif { [string compare "\}" $token] == 0 } {
+            incr curly_close
+          } elseif { [string match m_* "$token"] == 1 } {
+            set token_end [expr [string wordend $data $start ] - 1]
+            set ivar [string range $token 2 end]
+            set ivar [string trim $ivar]
+
+            if { [list_contains "$class_name.i.$ivar"] == 1 } {
+              set class_list($class_name.i.$ivar) 1
+            } elseif { $verbose } {
+              puts "\tIvar Issue:\t\tCan't find $class_name.i.$ivar"
+            }
+          } elseif { [string compare "this" $token] == 0 } {
+            set start [expr $start + 2]
+            set token_end [expr [string wordend $data $start ] - 1]
+            set ivar [string range $data $start $token_end]
+            if { [string first "Get" $ivar] > -1 } {
+              set start [expr $start + 3];
+
+              # Check if this is a Get*AsString() method
+              if { [string first "AsString" $ivar] > -1 } {
+                set token_end [expr $token_end - 8];
+              }
+
+              set ivar [string range $data $start $token_end]
+            } 
+            set ivar [string trim $ivar]
+
+            if { [list_contains "$class_name.i.$ivar"] == 1 } {
+              set class_list($class_name.i.$ivar) 1
+            } elseif { $verbose } {
+              puts "\tIvar Issue:\t\tCan't find $class_name.i.$ivar"
+            }
+          }
+        }
+
+        if { $curly_open == $curly_close } {
+          set search_state 3
+        }
+      }
+    }
+
+    close $fileid
+  }
+}
+
+proc read_directory { dirname } {
+
+  global class_name
+  global argv
+
+  set total_defects 0
+
+  set files [glob -nocomplain "$dirname/itk*.h"]
+
+  if { $files != "" } {
+    foreach headername $files {
+
+      set class_name ""
+
+      # Check that a PrintSelf() is defined
+      check_header_file $headername
+
+      # Check that the PrintSelf() method accesses the appropriate ivars 
+      if { $class_name != "" && [list_contains "$class_name.p"] == 1 } {
+        set length [string length $headername]
+        set filename [string range $headername 0 [expr $length - 3] ]
+        if {[file exists "$filename.txx"] == 1} {
+          check_printself "$filename.txx"
+        } elseif {[file exists "$filename.cxx"] == 1} {
+          check_printself "$filename.cxx"
+        } elseif {[file exists "$filename.h"] == 1} {
+             check_printself "$filename.h" 
+        }
+      }
+
+    }
+  }
+}
+
+proc class_has_ivars { class } {
+
+  global verbose
+  global class_list
+
+  set searchid [array startsearch class_list]
+
+  while { [array anymore class_list $searchid] } {
+
+    set element [array nextelement class_list $searchid]
+
+    if { [string match "$class.i.*" $element] == 1 } {
+      array donesearch class_list $searchid
+      return 1
+    }
+  }
+
+  array donesearch class_list $searchid
+
+  return 0
+}
+
+proc check_for_defects { print } {
+
+  global pd_id
+
+  global verbose
+  global class_list
+  global class_print_count
+  global ivar_miss_count
+  global printself_miss_count
+  global super_miss_count
+
+  #
+  #		PRINTSELF CHECK
+  #
+
+  # Loop through list and count printself defects, if any
+  set searchid [array startsearch class_list]
+
+  while { [array anymore class_list $searchid] } {
+
+    set element [array nextelement class_list $searchid]
+    # Extract strings that represent PrintSelfs
+    if { [string match "*.p" $element] == 1 } {
+      set end [expr [string wordend $element 0] - 1]
+      set curr_class [string range $element 0 $end]
+
+      if { [class_has_ivars $curr_class] == 1 } {
+
+        incr class_print_count
+
+        if { $class_list($element) != 1 } {
+
+          incr printself_miss_count
+        }
+      }
+    }
+  }
+
+  array donesearch class_list $searchid
+
+  # Loop through list and print printself defects
+  if { $printself_miss_count > 0 && $print } {
+    puts $pd_id "  PrintSelf DEFECTS: "
+    set searchid [array startsearch class_list]
+
+    while { [array anymore class_list $searchid] } {
+
+      set element [array nextelement class_list $searchid]
+      # Extract strings that represent PrintSelfs
+      if { [string match "*.p" $element] == 1 } {
+        set end [expr [string wordend $element 0] - 1]
+        set curr_class [string range $element 0 $end]
+
+        if { [class_has_ivars $curr_class] == 1 } {
+          if { $class_list($element) != 1 } {
+            puts $pd_id "    $curr_class does not have a PrintSelf method"
+          }
+        }
+      }
+    }
+
+    array donesearch class_list $searchid
+  }
+
+  #
+  #		SUPERCLASS CHECK
+  #
+
+  # Loop through list and count superclass defects, if any
+  set searchid [array startsearch class_list]
+
+  while { [array anymore class_list $searchid] } {
+
+    set element [array nextelement class_list $searchid]
+    # Extract strings that represent superclasses
+    if { [string match "*.s.*" $element] == 1 } {
+      set end [expr [string wordend $element 0] - 1]
+      set curr_class [string range $element 0 $end]
+
+      if { [class_has_ivars $curr_class] == 1 &&
+           $class_list($element) != 1 } {
+
+        incr super_miss_count
+      }
+    }
+  }
+
+  array donesearch class_list $searchid
+
+  # Loop through list and print superclass defects
+  if { $super_miss_count > 0  && $print } {
+    puts $pd_id "  Superclass DEFECTS: "
+    set searchid [array startsearch class_list]
+
+    while { [array anymore class_list $searchid] } {
+
+      set element [array nextelement class_list $searchid]
+      # Extract strings that represent superclasses
+      if { [string match "*.s.*" $element] == 1 } {
+        set end [expr [string wordend $element 0] - 1]
+        set curr_class [string range $element 0 $end]
+
+        if { [class_has_ivars $curr_class] == 1 &&
+             $class_list($element) != 1 } {
+
+            set start [expr $end + 4]
+            set end [expr [string wordend $element $start] - 1]
+            set parent [string range $element $start $end]
+
+            puts $pd_id "    $curr_class did not print superclass"
+        }
+      }
+    }
+
+    array donesearch class_list $searchid
+  }
+
+  #
+  #		IVAR CHECK
+  #
+
+  # Loop through list and count ivar defects, if any
+  set searchid [array startsearch class_list]
+
+  while { [array anymore class_list $searchid] } {
+
+    set element [array nextelement class_list $searchid]
+
+    # Extract strings that represent ivars
+    if { [string match "*.i.*" $element] == 1 } {
+      if { $class_list($element) != 1 } {
+          incr ivar_miss_count
+
+      }
+    }
+  }
+
+  array donesearch class_list $searchid
+
+  # Loop through list and print ivar defects
+  if { $ivar_miss_count > 0 && $print } {
+    puts $pd_id "  Ivar DEFECTS: "
+    set searchid [array startsearch class_list]
+
+    while { [array anymore class_list $searchid] } {
+
+      set element [array nextelement class_list $searchid]
+
+      # Extract strings that represent ivars
+      if { [string match "*.i.*" $element] == 1 } {
+        if { $class_list($element) != 1 } {
+          set end [expr [string wordend $element 0] - 1]
+          set curr_class [string range $element 0 $end]
+
+          set start [expr $end + 4]
+          set end [expr [string wordend $element $start] - 1]
+          set ivar [string range $element $start $end]
+
+          puts $pd_id "    $curr_class does not print ivar: m_$ivar"
+        }
+      }
+    }
+
+    array donesearch class_list $searchid
+  }
+
+}
+
+proc print_toolkit_results { toolkit } {
+
+  global pd_id
+
+  global class_count
+  global class_print_count
+  global printself_miss_count
+  global ivar_count
+  global ivar_miss_count
+  global super_miss_count
+
+  check_for_defects 1
+
+  set tk [string range $toolkit 0 14 ]
+
+}
+
+proc print_totals {} {
+  global total_defects
+  global total_class_count
+  global total_class_print_count
+  global total_printself_miss_count
+  global total_ivar_count
+  global total_ivar_miss_count
+  global total_super_miss_count
+
+  set total_defects [expr $total_printself_miss_count + $total_super_miss_count + $total_ivar_miss_count]
+
+}
+
+proc open_files { } {
+
+  global pd_id
+
+  set pd_id stdout
+
+}
+
+proc close_files { } {
+
+  global pd_id
+
+  close $pd_id
+
+  set pd_id 0
+}
+
+proc clear_results { } {
+
+  global class_count
+  global class_print_count
+  global printself_miss_count
+  global ivar_count
+  global ivar_miss_count
+  global super_miss_count
+  global class_list
+
+  unset class_list
+  set class_list(null) 1
+
+  set class_count 0
+  set class_print_count 0
+  set ivar_count 0
+  set printself_miss_count 0
+  set ivar_miss_count 0
+  set super_miss_count 0
+}
+
+proc measure_itk {kits} {
+
+  global pd_id
+
+  global verbose
+
+  global class_list
+  global class_count
+  global class_print_count
+  global printself_miss_count
+  global ivar_count
+  global ivar_miss_count
+  global super_miss_count
+
+  global total_class_count
+  global total_class_print_count
+  global total_printself_miss_count
+  global total_ivar_count
+  global total_ivar_miss_count
+  global total_super_miss_count
+
+  set path ""
+
+  open_files
+
+  foreach toolkit $kits {
+    clear_results
+
+    puts $pd_id " "
+    puts $pd_id "Results for directory: $toolkit"
+
+    read_directory $path$toolkit
+
+    print_toolkit_results $toolkit
+
+    set total_class_count [expr $total_class_count + $class_count]
+    set total_class_print_count [expr $total_class_print_count + $class_print_count]
+    set total_printself_miss_count [expr $total_printself_miss_count + $printself_miss_count];
+    set total_ivar_count [expr $total_ivar_count + $ivar_count];
+    set total_ivar_miss_count [expr $total_ivar_miss_count + $ivar_miss_count];
+    set total_super_miss_count [expr $total_super_miss_count + $super_miss_count];
+  }
+
+  print_totals
+
+
+
+  if { $verbose } {
+    parray class_list
+  }
+  close_files
+}
+measure_itk [lindex $argv 0]
+
+exit $total_defects
diff --git a/Utilities/ITK/Utilities/Dart/cronentry.in b/Utilities/ITK/Utilities/Dart/cronentry.in
new file mode 100644
index 0000000000000000000000000000000000000000..6c627433282e8f91403e2ab5fb7c400d0f61aaf0
--- /dev/null
+++ b/Utilities/ITK/Utilities/Dart/cronentry.in
@@ -0,0 +1,6 @@
+# Attempt a continuous build every 10 minutes
+5,15,25,35,45,55 * * * * @ITK_BINARY_DIR@/BuildContinuous.sh &> @ITK_BINARY_DIR@/Testing/Temporary/cronlog
+# Prevent the continuous build
+0 0 * * * @ITK_BINARY_DIR@/PreventContinuous.sh
+# Allow the continuous build
+0 6 * * * @ITK_BINARY_DIR@/AllowContinuous.sh
diff --git a/Utilities/ITK/Utilities/Doxygen/cvsVersionFilter.sh b/Utilities/ITK/Utilities/Doxygen/cvsVersionFilter.sh
new file mode 100644
index 0000000000000000000000000000000000000000..3ae7d6010992c0659c9dcfcf5e59083093ff8174
--- /dev/null
+++ b/Utilities/ITK/Utilities/Doxygen/cvsVersionFilter.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+cvs -d :pserver:anonymous@www.itk.org:/cvsroot/Insight status $1 | sed -n 's/^[ \]*Working revision:[ \t]*\([0-9][0-9\.]*\).*/\1/p'
+
diff --git a/Utilities/ITK/Utilities/Doxygen/doxygen.config.in b/Utilities/ITK/Utilities/Doxygen/doxygen.config.in
new file mode 100644
index 0000000000000000000000000000000000000000..dd5524b43e21a09230283a32f90d74fa86b28c33
--- /dev/null
+++ b/Utilities/ITK/Utilities/Doxygen/doxygen.config.in
@@ -0,0 +1,1348 @@
+# Doxyfile 1.4.3-20050530
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = ITK
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = @ITK_VERSION_MAJOR@.@ITK_VERSION_MINOR@.@ITK_VERSION_PATCH@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = @ITK_BINARY_DIR@/Documentation/Doxygen
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+# ITKcommments: Links specific to ITK will then require relative paths or absolute
+# paths and will create issues. 
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = NO
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = @ITK_BINARY_DIR@/Documentation/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 2
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation.
+
+SHOW_DIRECTORIES       = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from the 
+# version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the progam writes to standard output 
+# is used as the file version. See the manual for examples.
+#
+# FILE_VERSION_FILTER    = "@ITK_SOURCE_DIR@/Utilities/Doxygen/cvsVersionFilter.sh"
+#
+
+FILE_VERSION_FILTER    = 
+
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = "@ITK_SOURCE_DIR@/Code" "@ITK_SOURCE_DIR@/Documentation/Doxygen"
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS          = *.h *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = "@ITK_SOURCE_DIR@/Code/Common/itkPixelTraits.h" \
+                         "@ITK_SOURCE_DIR@/Code/Common/itkNumericTraits.h" \
+                         "@ITK_SOURCE_DIR@/Code/Common/itkNumericTraitsRGB.h" \
+                         "@ITK_SOURCE_DIR@/Code/Common/itkNumericTraitsVectorPixel.h" \
+                         "@ITK_SOURCE_DIR@/Code/Common/itkNumericTraitsTensorPixel.h" \
+                         "@ITK_SOURCE_DIR@/Code/Common/itkNumericTraitsCovariantVectorPixel.h" \
+                         "@ITK_SOURCE_DIR@/Code/Common/itkNumericTraitsVariableLengthVectorPixel.h" \
+                         "@ITK_SOURCE_DIR@/Code/IO/itkPixelData.h" \
+                         "@ITK_SOURCE_DIR@/Code/IO/itkAnalyzeDbh.h" 
+
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = "*/vxl_copyright.h" "*/vcl/*" "*/dll.h" \
+                         "*/test*" "*/example*" "*config*" "*/contrib/*" \
+                         "*/Templates/*" "*_mocced.cxx" # "*impl*"
+
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = "@ITK_SOURCE_DIR@/Testing/Code" "@ITK_SOURCE_DIR@/Examples" "@ITK_SOURCE_DIR@/Examples/DataRepresentation/Image"
+
+
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = *.cxx
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = YES
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = "@ITK_SOURCE_DIR@/Documentation/Art"
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = "perl @ITK_BINARY_DIR@/itkdoxygen.pl"
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 3
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = "@ITK_SOURCE_DIR@/Documentation/Doxygen/DoxygenHeader.html"
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = "@ITK_SOURCE_DIR@/Documentation/Doxygen/DoxygenFooter.html"
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =   "@ITK_SOURCE_DIR@/Documentation/Doxygen/DoxygenStyle.css"
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = YES
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 1
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = YES
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = NO
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED  =  "itkNotUsed(x)="\
+               "itkSetMacro(name,type)= \
+                  virtual void Set##name (type _arg);" \
+               "itkGetMacro(name,type)= \
+                  virtual type Get##name ();" \
+               "itkGetConstMacro(name,type)= \
+                  virtual type Get##name () const;" \
+               "itkSetStringMacro(name)= \
+                  virtual void Set##name (const char* _arg);" \
+               "itkGetStringMacro(name)= \
+                  virtual const char* Get##name () const;" \
+               "itkSetClampMacro(name,type,min,max)= \
+                  virtual void Set##name (type _arg);" \
+               "itkSetObjectMacro(name,type)= \
+                  virtual void Set##name (type* _arg);" \
+               "itkGetObjectMacro(name,type)= \
+                  virtual type* Get##name ();" \
+               "itkSetConstObjectMacro(name,type)= \
+                  virtual void Set##name ( const type* _arg);" \
+               "itkGetConstObjectMacro(name,type)= \
+                  virtual const type* Get##name ();" \
+               "itkGetConstReferenceMacro(name,type)= \
+                  virtual const type& Get##name ();" \
+               "itkGetConstReferenceObjectMacro(name,type)= \
+                  virtual const type::Pointer& Get##name () const;" \
+               "itkBooleanMacro(name)= \
+                  virtual void name##On (); \
+                  virtual void name##Off ();" \
+               "itkSetVector2Macro(name,type)= \
+                  virtual void Set##name (type _arg1, type _arg2) \
+                  virtual void Set##name (type _arg[2]);" \
+               "itkGetVector2Macro(name,type)= \
+                  virtual type* Get##name () const; \
+                  virtual void Get##name (type& _arg1, type& _arg2) const; \
+                  virtual void Get##name (type _arg[2]) const;" \
+               "itkSetVector3Macro(name,type)= \
+                  virtual void Set##name (type _arg1, type _arg2, type _arg3) \
+                  virtual void Set##name (type _arg[3]);" \
+               "itkGetVector3Macro(name,type)= \
+                  virtual type* Get##name () const; \
+                  virtual void Get##name (type& _arg1, type& _arg2, type& _arg3) const; \
+                  virtual void Get##name (type _arg[3]) const;" \
+               "itkSetVector4Macro(name,type)= \
+                  virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4) \
+                  virtual void Set##name (type _arg[4]);" \
+               "itkGetVector4Macro(name,type)= \
+                  virtual type* Get##name () const; \
+                  virtual void Get##name (type& _arg1, type& _arg2, type& _arg3, type& _arg4) const; \
+                  virtual void Get##name (type _arg[4]) const;" \
+               "itkSetVector6Macro(name,type)= \
+                  virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4, type _arg5, type _arg6) \
+                  virtual void Set##name (type _arg[6]);" \
+               "itkGetVector6Macro(name,type)= \
+                  virtual type* Get##name () const; \
+                  virtual void Get##name (type& _arg1, type& _arg2, type& _arg3, type& _arg4, type& _arg5, type& _arg6) const; \
+                  virtual void Get##name (type _arg[6]) const;" \
+               "itkSetVectorMacro(name,type,count)= \
+                  virtual void Set##name(type data[]);" \
+               "itkGetVectorMacro(name,type,count)= \
+                  virtual type* Get##name () const;" \
+               "itkNewMacro(type)= \
+                  static Pointer New();" \
+               "itkTypeMacro(thisClass,superclass)= \
+                  virtual const char *GetNameOfClass() const;" \
+               "itkEventMacro(thisClass,superclass)= \
+                  class thisClass : public superclass {};" \
+               "itkConceptMacro(name,concept)= \
+                  enum { name = 0 };" \
+               "vcl_numeric_limits= \
+                  std::numeric_limits" \
+               "ITK_TYPENAME= \
+                  typename" \
+               "FEM_ABSTRACT_CLASS(thisClass,parentClass)= \
+                  public:                                               \
+                    /** Standard "Self" typedef.*/                      \
+                    typedef thisClass Self;                             \
+                    /** Standard "Superclass" typedef. */               \
+                    typedef parentClass Superclass;                     \
+                    /** Pointer or SmartPointer to an object. */        \
+                    typedef Self* Pointer;                              \
+                    /** Const pointer or SmartPointer to an object. */  \
+                    typedef const Self* ConstPointer;                   \
+                  private:"                                             \
+               "FEM_CLASS(thisClass,parentClass)= \
+                  FEM_ABSTRACT_CLASS(thisClass,parentClass)             \
+                  public:                                               \
+                    /** Create a new object from the existing one  */   \
+                    virtual Baseclass::Pointer Clone() const;           \
+                    /** Class ID for FEM object factory */              \
+                    static const int CLID;                              \
+                    /** Virtual function to access the class ID */      \
+                    virtual int ClassID() const                         \
+                      { return CLID; }                                  \
+                    /** Object creation in an itk compatible way */     \
+                    static Self::Pointer New()                          \
+                      { return new Self(); }                            \
+                  private:"                                             \
+		"FREEVERSION" "ERROR_CHECKING"                          \
+                "HAS_TIFF" "HAS_JPEG" "HAS_NETLIB" "HAS_PNG" "HAS_ZLIB" \
+                "HAS_GLUT" "HAS_QT"                                     \
+               "VCL_USE_NATIVE_STL=1" "VCL_USE_NATIVE_COMPLEX=1"        \
+               "VCL_HAS_BOOL=1" "VXL_BIG_ENDIAN=1" "VXL_LITTLE_ENDIAN=0"\
+               "VNL_DLL_DATA=" "size_t=vcl_size_t"
+
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO 
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that a graph may be further truncated if the graph's 
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, which results in a white background. 
+# Warning: Depending on the platform used, enabling this option may lead to 
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
+# read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/Utilities/ITK/Utilities/Doxygen/itkdoxygen.pl.in b/Utilities/ITK/Utilities/Doxygen/itkdoxygen.pl.in
new file mode 100644
index 0000000000000000000000000000000000000000..33054b5ea0953aea8452349f0fcec2e62589e0f2
--- /dev/null
+++ b/Utilities/ITK/Utilities/Doxygen/itkdoxygen.pl.in
@@ -0,0 +1,9 @@
+# for vxl files run the vxl_doxy.pl script, and use itkgroup.pl for all other files
+if ( $ARGV[0] =~ /(vxl|vcl|vnl)/) 
+{
+    system ("perl @ITK_SOURCE_DIR@/Utilities/Doxygen/vxl_doxy.pl $ARGV[0]");
+}
+else
+{
+    system ("perl @ITK_SOURCE_DIR@/Utilities/Doxygen/itkgroup.pl $ARGV[0]");
+}
diff --git a/Utilities/ITK/Utilities/Doxygen/itkgroup.pl b/Utilities/ITK/Utilities/Doxygen/itkgroup.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f5276d3f7f84d6eb89288ef94844c37a32ce87a6
--- /dev/null
+++ b/Utilities/ITK/Utilities/Doxygen/itkgroup.pl
@@ -0,0 +1,84 @@
+# if regular doxycomment add a @{
+# at next empty line add a //@}
+
+$ingroup = 0;
+$semicount =0;
+$endbracecount = 0;
+$endparencount = 0;
+while(<>)
+{
+    chomp;
+    $line = $_;
+# if the line is not an empty line
+    if( $line =~ /\S+/ )
+    {
+	if ( /\/\*\*(.*)/ )
+	{
+            # I guess it was not a group, dump savebuffer
+            if($ingroup)
+            { 
+                print "/**" . $savebuffer . "\n";
+            }
+            # if it is a class or brief then output the line but
+            # do not start a group
+	    if ( /(\\class|\\brief)/ )
+	    {
+		print $line . "\n";
+	    }
+            # must be a group so start saving
+	    else
+	    {
+                $savebuffer = "$1" . "\n";
+		$ingroup = 1;
+                $semicount = 0;
+                $endbracecount = 0;
+                $endparencount = 0;
+	    }
+	}
+	else
+	{
+            # add to save buffer if in group
+            if($ingroup)
+            {
+                $savebuffer = $savebuffer . $_ . "\n";
+            }
+            else
+            {
+                # non empty line that is not the start of a doxy comment
+                print $_ . "\n";
+            }
+	}
+        if($line =~ /;/ )
+        {
+            $semicount = $semicount + 1;
+        }
+        if($line =~ /\}/ )
+        {
+            $endbracecount = $endbracecount + 1;
+        }
+        if($line =~ /\)/ )
+        {
+            $endparencount = $endparencount + 1;
+        }
+    }
+    else
+    {
+	if($ingroup)
+	{
+            if($endparencount > 1 && ($semicount > 1 || $endbracecount > 1))
+            {
+                print "/**@\{" . $savebuffer . "//@}\n\n";
+            }
+            else
+            {
+                print "/**" . $savebuffer . "\n";
+            }
+            $savebuffer = "";
+	    $ingroup = 0;
+	}
+	else
+	{
+	    print $line . "\n";
+	}
+    }
+}
diff --git a/Utilities/ITK/Utilities/Doxygen/vxl_doxy.pl b/Utilities/ITK/Utilities/Doxygen/vxl_doxy.pl
new file mode 100644
index 0000000000000000000000000000000000000000..f3590259f8b2b54921bf5db6a48cae319027cdb1
--- /dev/null
+++ b/Utilities/ITK/Utilities/Doxygen/vxl_doxy.pl
@@ -0,0 +1,127 @@
+#!/bin/sh
+# -*- perl -*-
+exec perl -w -x $0 ${1+"$@"}
+#!perl
+#line 6
+# If Windows barfs at line 3 here, you will need to run perl -x vxl_doxy.pl
+# You can set up as a permanent file association using the following commands
+#  >assoc .pl-PerlScript
+#  >ftype PerlScript=Perl=C:\Perl\bin\Perl.exe -x "%1" %* 
+
+# Script to change the perceps documentation format to Doxygen (JavaDoc) format
+# Authors:
+#         Dave Cooper
+#         Maarten Vergauwen
+# Date:
+#      17/02/2000
+# Modified:
+# 11 April 2001 Ian Scott.   Remove support for old perceps commands
+#  5 May   2001 Geoff Cross. Correctly handle end of verbatim blocks. Allow two contiguous comments
+#  10 May  2001 Ian Scott. Merged Geoffs and my changes
+
+
+# patterns to be matched
+$verbpatt = '\\\\verbatim';
+$endverbpatt = '\\\\endverbatim';
+$slashslashpatt = '^\\s*//';
+$slashslashcolonpatt = '^\\s*//:';
+$slashstarstarpatt = '/**';
+$spacespacepatt = '  ';
+$starpatt = '*';
+$starslashpatt = '*/';
+
+# variables that keep state:
+
+# comment found -> first line should start with /**, next lines with *, last line with */
+$comment = 0;
+
+# verbatim found -> lines should not start with * (visible in Doxygen)
+$verbatim = 0;
+# finish verbatim mode at the end of this line.
+$should_end_verbatim = 0;
+
+$debug = 0;
+
+# mainloop
+while (<>)
+{
+    # preprocessing
+    s/\bVCL_SUNPRO_CLASS_SCOPE_HACK\s*\([^()]*\)//g;
+    s/\bVCL_SUNPRO_ALLOCATOR_HACK\s*\(([^()]*)\)/$1/g;
+    s/\bVCL_CAN_STATIC_CONST_INIT_(INT|FLOAT)\b/1/g;
+    s/\bVCL_STATIC_CONST_INIT_(INT|FLOAT)\s*\(([^()]*)\)/= $2/g;
+    s/\bVCL_DFL_TYPE_PARAM_STLDECL\s*\(([^,()]*),([^,()]*)\)/class $1 = $2 /g;
+    s/\bDECLARE_DYNCREATE\s*\([^()]*\)//g; # for MFC
+
+    if ( $should_end_verbatim )
+    {
+        $verbatim = 0;
+        $should_end_verbatim = 0;
+    }
+
+    # found verbatim ?
+    if ( m/$verbpatt/ ) { $verbatim = 1; };
+
+    # found endverbatim ?
+    if ( m/$endverbpatt/ ) { $should_end_verbatim = 1; };
+
+    # found start of comment: "//:"  ?
+    if ( s!$slashslashcolonpatt!$slashstarstarpatt! )
+    {
+        chomp; s/\s*$//;
+        # escape a space following a dot, add a dot at the end,
+#       # and finish brief doc, unless the line is empty or only has '\file':
+        unless (m!^\s*\/\*\*\s*(\\file)?\s*$!) {
+#         s/\. /.\\ /g; s/(\.)?\s*$/. \*\/\n\/\*/;
+          s/\. /.\\ /g; s/(\.)?\s*$/.\n/;
+        }
+        else { s/$/\n/; }
+
+        if ($comment)
+        {
+            # Previous comment hasn't ended--two contiguous comment blocks.
+            # (Should not happen.)
+            print STDERR "Two contiguous comment blocks -- this should not happen\n";
+            print "*/\n";
+        }
+        $comment = 1;
+        print; next;
+    }
+
+    # Replace '$' with '\f$' (TeX math mode)
+    s/(\\f)?\$(.+?)(\\f)?\$/\\f\$$2\\f\$/g if ($comment);
+
+    # found continuation of comment WITH verbatim -> no "*"
+    if ( m!$slashslashpatt! && $verbatim && $comment)
+    {
+        s!$slashslashpatt!$spacespacepatt!;
+#       # Make 'Modifications' a section title:
+#       s!\b(Modifications?)\b\:?!\<H2\>$1\<\/H2\>!;
+        # remove lines of the form ========= or +-+-+-+-+ or ********* or longer:
+        print unless m/^\s*[*=+-]{9,}\s*$/; next;
+    }
+
+    # found continuation of comment WITHOUT verbatim -> start line with "*"
+    if ( m!$slashslashpatt! && $comment )
+    {
+        s!$slashslashpatt!$starpatt!;
+        # remove lines of the form ========= or +-+-+-+-+ or ********* or longer:
+        print unless m/^\s*[*=+-]{9,}\s*$/; next;
+    }
+
+    # found end of comment -> start line with */
+    # NOTE that *every* line within a comment (also empty lines) *must* start with // !
+    # (In an earlier version of this script, empty lines were allowed inside comments.)
+    if ( $comment && ! m!$slashslashpatt!  )
+    {
+        print "$starslashpatt\n";
+        $comment = 0;
+        print; next;
+    }
+
+    # just print line if not in comment or in file
+    if ( !$comment ) { print; next; }
+
+    # debug - print unprocessed lines (s.b. none)
+    if ($debug) { print "LNP:\t"; print; }
+}
diff --git a/Utilities/ITK/Utilities/expat/CMakeLists.txt b/Utilities/ITK/Utilities/expat/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0aef28bcae371ea7debd322e19befefeae097c68
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/CMakeLists.txt
@@ -0,0 +1,25 @@
+PROJECT(ITKEXPAT)
+INCLUDE_REGULAR_EXPRESSION("^(expat|xml|ascii|utf|name|iascii|latin).*$")
+
+SET(expat_SRCS
+  xmltok.c xmlparse.c  xmlrole.c
+)
+
+INCLUDE_DIRECTORIES(BEFORE ${ITKEXPAT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(BEFORE ${ITKEXPAT_BINARY_DIR})
+
+IF(WIN32)
+  IF(NOT BUILD_SHARED_LIBS)
+    SET (ITK_EXPAT_STATIC 1)
+  ENDIF(NOT BUILD_SHARED_LIBS)
+ENDIF(WIN32)
+
+CONFIGURE_FILE(${ITKEXPAT_SOURCE_DIR}/expatConfig.h.in
+               ${ITKEXPAT_BINARY_DIR}/expatConfig.h)
+CONFIGURE_FILE(${ITKEXPAT_SOURCE_DIR}/expatDllConfig.h.in
+               ${ITKEXPAT_BINARY_DIR}/expatDllConfig.h)
+
+ADD_LIBRARY(ITKEXPAT ${expat_SRCS})
+
+INSTALL_TARGETS(/lib/InsightToolkit ITKEXPAT)
+INSTALL_FILES(/include/InsightToolkit/expat .h expat expatDllConfig)
diff --git a/Utilities/ITK/Utilities/expat/COPYING b/Utilities/ITK/Utilities/expat/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..fc97b02d90982cd28582dbe7ea056973bd9711af
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/COPYING
@@ -0,0 +1,21 @@
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+                               and Clark Cooper
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Utilities/ITK/Utilities/expat/ascii.h b/Utilities/ITK/Utilities/expat/ascii.h
new file mode 100644
index 0000000000000000000000000000000000000000..6376b1f311b329df16489a3504786e670609ea05
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/ascii.h
@@ -0,0 +1,86 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#define ASCII_A 0x41
+#define ASCII_B 0x42
+#define ASCII_C 0x43
+#define ASCII_D 0x44
+#define ASCII_E 0x45
+#define ASCII_F 0x46
+#define ASCII_G 0x47
+#define ASCII_H 0x48
+#define ASCII_I 0x49
+#define ASCII_J 0x4A
+#define ASCII_K 0x4B
+#define ASCII_L 0x4C
+#define ASCII_M 0x4D
+#define ASCII_N 0x4E
+#define ASCII_O 0x4F
+#define ASCII_P 0x50
+#define ASCII_Q 0x51
+#define ASCII_R 0x52
+#define ASCII_S 0x53
+#define ASCII_T 0x54
+#define ASCII_U 0x55
+#define ASCII_V 0x56
+#define ASCII_W 0x57
+#define ASCII_X 0x58
+#define ASCII_Y 0x59
+#define ASCII_Z 0x5A
+
+#define ASCII_a 0x61
+#define ASCII_b 0x62
+#define ASCII_c 0x63
+#define ASCII_d 0x64
+#define ASCII_e 0x65
+#define ASCII_f 0x66
+#define ASCII_g 0x67
+#define ASCII_h 0x68
+#define ASCII_i 0x69
+#define ASCII_j 0x6A
+#define ASCII_k 0x6B
+#define ASCII_l 0x6C
+#define ASCII_m 0x6D
+#define ASCII_n 0x6E
+#define ASCII_o 0x6F
+#define ASCII_p 0x70
+#define ASCII_q 0x71
+#define ASCII_r 0x72
+#define ASCII_s 0x73
+#define ASCII_t 0x74
+#define ASCII_u 0x75
+#define ASCII_v 0x76
+#define ASCII_w 0x77
+#define ASCII_x 0x78
+#define ASCII_y 0x79
+#define ASCII_z 0x7A
+
+#define ASCII_0 0x30
+#define ASCII_1 0x31
+#define ASCII_2 0x32
+#define ASCII_3 0x33
+#define ASCII_4 0x34
+#define ASCII_5 0x35
+#define ASCII_6 0x36
+#define ASCII_7 0x37
+#define ASCII_8 0x38
+#define ASCII_9 0x39
+
+#define ASCII_TAB 0x09
+#define ASCII_SPACE 0x20 
+#define ASCII_EXCL 0x21
+#define ASCII_QUOT 0x22
+#define ASCII_AMP 0x26
+#define ASCII_APOS 0x27
+#define ASCII_MINUS 0x2D
+#define ASCII_PERIOD 0x2E
+#define ASCII_COLON 0x3A
+#define ASCII_SEMI 0x3B
+#define ASCII_LT 0x3C
+#define ASCII_EQUALS 0x3D
+#define ASCII_GT 0x3E
+#define ASCII_LSQB 0x5B
+#define ASCII_RSQB 0x5D
+#define ASCII_UNDERSCORE 0x5F
diff --git a/Utilities/ITK/Utilities/expat/asciitab.h b/Utilities/ITK/Utilities/expat/asciitab.h
new file mode 100644
index 0000000000000000000000000000000000000000..eb445cc52c15847132988397b594e0e4bae10347
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/asciitab.h
@@ -0,0 +1,37 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/Utilities/ITK/Utilities/expat/expat.h b/Utilities/ITK/Utilities/expat/expat.h
new file mode 100644
index 0000000000000000000000000000000000000000..d4eee5cdd35d7b5f14c4ecb4dccc39eeb51f1cc0
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/expat.h
@@ -0,0 +1,739 @@
+/*
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#ifndef XmlParse_INCLUDED
+#define XmlParse_INCLUDED 1
+
+#include <stdlib.h>
+
+#include "expatDllConfig.h"
+
+#if defined(_WIN32) && !defined(ITK_EXPAT_STATIC)
+#  if defined(vtkexpat_EXPORTS)
+#    define XMLPARSEAPI(type) __declspec( dllexport ) type __cdecl
+#  else
+#    define XMLPARSEAPI(type) __declspec( dllimport ) type __cdecl
+#  endif
+#else
+#  define XMLPARSEAPI(type) type
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *XML_Parser;
+
+/* Information is UTF-8 encoded. */
+typedef char XML_Char;
+typedef char XML_LChar;
+
+enum XML_Content_Type {
+  XML_CTYPE_EMPTY = 1,
+  XML_CTYPE_ANY,
+  XML_CTYPE_MIXED,
+  XML_CTYPE_NAME,
+  XML_CTYPE_CHOICE,
+  XML_CTYPE_SEQ
+};
+
+enum XML_Content_Quant {
+  XML_CQUANT_NONE,
+  XML_CQUANT_OPT,
+  XML_CQUANT_REP,
+  XML_CQUANT_PLUS
+};
+
+/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be
+   XML_CQUANT_NONE, and the other fields will be zero or NULL.
+   If type == XML_CTYPE_MIXED, then quant will be NONE or REP and
+   numchildren will contain number of elements that may be mixed in
+   and children point to an array of XML_Content cells that will be
+   all of XML_CTYPE_NAME type with no quantification.
+
+   If type == XML_CTYPE_NAME, then the name points to the name, and
+   the numchildren field will be zero and children will be NULL. The
+   quant fields indicates any quantifiers placed on the name.
+
+   CHOICE and SEQ will have name NULL, the number of children in
+   numchildren and children will point, recursively, to an array
+   of XML_Content cells.
+
+   The EMPTY, ANY, and MIXED types will only occur at top level.
+*/
+
+typedef struct XML_cp XML_Content;
+
+struct XML_cp {
+  enum XML_Content_Type         type;
+  enum XML_Content_Quant        quant;
+  XML_Char *                    name;
+  unsigned int                  numchildren;
+  XML_Content *                 children;
+};
+
+
+/* This is called for an element declaration. See above for
+   description of the model argument. It's the caller's responsibility
+   to free model when finished with it.
+*/
+
+typedef void (*XML_ElementDeclHandler) (void *userData,
+                                        const XML_Char *name,
+                                        XML_Content *model);
+
+XMLPARSEAPI(void)
+XML_SetElementDeclHandler(XML_Parser parser,
+                          XML_ElementDeclHandler eldecl);
+
+/*
+  The Attlist declaration handler is called for *each* attribute. So
+  a single Attlist declaration with multiple attributes declared will
+  generate multiple calls to this handler. The "default" parameter
+  may be NULL in the case of the "#IMPLIED" or "#REQUIRED" keyword.
+  The "isrequired" parameter will be true and the default value will
+  be NULL in the case of "#REQUIRED". If "isrequired" is true and
+  default is non-NULL, then this is a "#FIXED" default.
+ */
+
+typedef void (*XML_AttlistDeclHandler) (void           *userData,
+                                        const XML_Char *elname,
+                                        const XML_Char *attname,
+                                        const XML_Char *att_type,
+                                        const XML_Char *dflt,
+                                        int             isrequired);
+
+XMLPARSEAPI(void)
+XML_SetAttlistDeclHandler(XML_Parser parser,
+                          XML_AttlistDeclHandler attdecl);
+
+
+  /* The XML declaration handler is called for *both* XML declarations and
+     text declarations. The way to distinguish is that the version parameter
+     will be null for text declarations. The encoding parameter may be null
+     for XML declarations. The standalone parameter will be -1, 0, or 1
+     indicating respectively that there was no standalone parameter in
+     the declaration, that it was given as no, or that it was given as yes.
+  */
+
+typedef void (*XML_XmlDeclHandler) (void                *userData,
+                                    const XML_Char      *version,
+                                    const XML_Char      *encoding,
+                                    int                  standalone);
+
+XMLPARSEAPI(void)
+XML_SetXmlDeclHandler(XML_Parser parser,
+                      XML_XmlDeclHandler xmldecl);
+
+
+typedef struct {
+  void *(*malloc_fcn)(size_t size);
+  void *(*realloc_fcn)(void *ptr, size_t size);
+  void (*free_fcn)(void *ptr);
+} XML_Memory_Handling_Suite;
+
+/* Constructs a new parser; encoding is the encoding specified by the
+external protocol or null if there is none specified. */
+
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreate(const XML_Char *encoding);
+
+/* Constructs a new parser and namespace processor.  Element type
+names and attribute names that belong to a namespace will be expanded;
+unprefixed attribute names are never expanded; unprefixed element type
+names are expanded only if there is a default namespace. The expanded
+name is the concatenation of the namespace URI, the namespace
+separator character, and the local part of the name.  If the namespace
+separator is '\0' then the namespace URI and the local part will be
+concatenated without any separator.  When a namespace is not declared,
+the name and prefix will be passed through without expansion. */
+
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
+
+
+/* Constructs a new parser using the memory management suit referred to
+   by memsuite. If memsuite is NULL, then use the standard library memory
+   suite. If namespaceSeparator is non-NULL it creates a parser with
+   namespace processing as described above. The character pointed at
+   will serve as the namespace separator.
+
+   All further memory operations used for the created parser will come from
+   the given suite.
+*/
+
+XMLPARSEAPI(XML_Parser)
+XML_ParserCreate_MM(const XML_Char *encoding,
+                    const XML_Memory_Handling_Suite *memsuite,
+                    const XML_Char *namespaceSeparator);
+
+/* atts is array of name/value pairs, terminated by 0;
+   names and values are 0 terminated. */
+
+typedef void (*XML_StartElementHandler)(void *userData,
+                                        const XML_Char *name,
+                                        const XML_Char **atts);
+
+typedef void (*XML_EndElementHandler)(void *userData,
+                                      const XML_Char *name);
+
+
+/* s is not 0 terminated. */
+typedef void (*XML_CharacterDataHandler)(void *userData,
+                                         const XML_Char *s,
+                                         int len);
+
+/* target and data are 0 terminated */
+typedef void (*XML_ProcessingInstructionHandler)(void *userData,
+                                                 const XML_Char *target,
+                                                 const XML_Char *data);
+
+/* data is 0 terminated */
+typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data);
+
+typedef void (*XML_StartCdataSectionHandler)(void *userData);
+typedef void (*XML_EndCdataSectionHandler)(void *userData);
+
+/* This is called for any characters in the XML document for
+which there is no applicable handler.  This includes both
+characters that are part of markup which is of a kind that is
+not reported (comments, markup declarations), or characters
+that are part of a construct which could be reported but
+for which no handler has been supplied. The characters are passed
+exactly as they were in the XML document except that
+they will be encoded in UTF-8.  Line boundaries are not normalized.
+Note that a byte order mark character is not passed to the default handler.
+There are no guarantees about how characters are divided between calls
+to the default handler: for example, a comment might be split between
+multiple calls. */
+
+typedef void (*XML_DefaultHandler)(void *userData,
+                                   const XML_Char *s,
+                                   int len);
+
+/* This is called for the start of the DOCTYPE declaration, before
+   any DTD or internal subset is parsed. */
+
+typedef void (*XML_StartDoctypeDeclHandler)(void *userData,
+                                            const XML_Char *doctypeName,
+                                            const XML_Char *sysid,
+                                            const XML_Char *pubid,
+                                            int has_internal_subset);
+
+/* This is called for the start of the DOCTYPE declaration when the
+closing > is encountered, but after processing any external subset. */
+typedef void (*XML_EndDoctypeDeclHandler)(void *userData);
+
+/* This is called for entity declarations. The is_parameter_entity
+   argument will be non-zero if the entity is a parameter entity, zero
+   otherwise.
+
+   For internal entities (<!ENTITY foo "bar">), value will
+   be non-null and systemId, publicID, and notationName will be null.
+   The value string is NOT null terminated; the length is provided in
+   the value_length argument. Since it is legal to have zero-length
+   values, do not use this argument to test for internal entities.
+
+   For external entities, value will be null and systemId will be non-null.
+   The publicId argument will be null unless a public identifier was
+   provided. The notationName argument will have a non-null value only
+   for unparsed entity declarations.
+*/
+
+typedef void (*XML_EntityDeclHandler) (void *userData,
+                                       const XML_Char *entityName,
+                                       int is_parameter_entity,
+                                       const XML_Char *value,
+                                       int value_length,
+                                       const XML_Char *base,
+                                       const XML_Char *systemId,
+                                       const XML_Char *publicId,
+                                       const XML_Char *notationName);
+                                       
+XMLPARSEAPI(void)
+XML_SetEntityDeclHandler(XML_Parser parser,
+                         XML_EntityDeclHandler handler);
+
+/* OBSOLETE -- OBSOLETE -- OBSOLETE
+   This handler has been superceded by the EntityDeclHandler above.
+   It is provided here for backward compatibility.
+This is called for a declaration of an unparsed (NDATA)
+entity.  The base argument is whatever was set by XML_SetBase.
+The entityName, systemId and notationName arguments will never be null.
+The other arguments may be. */
+
+typedef void (*XML_UnparsedEntityDeclHandler)(void *userData,
+                                              const XML_Char *entityName,
+                                              const XML_Char *base,
+                                              const XML_Char *systemId,
+                                              const XML_Char *publicId,
+                                              const XML_Char *notationName);
+
+/* This is called for a declaration of notation.
+The base argument is whatever was set by XML_SetBase.
+The notationName will never be null.  The other arguments can be. */
+
+typedef void (*XML_NotationDeclHandler)(void *userData,
+                                        const XML_Char *notationName,
+                                        const XML_Char *base,
+                                        const XML_Char *systemId,
+                                        const XML_Char *publicId);
+
+/* When namespace processing is enabled, these are called once for
+each namespace declaration. The call to the start and end element
+handlers occur between the calls to the start and end namespace
+declaration handlers. For an xmlns attribute, prefix will be null.
+For an xmlns="" attribute, uri will be null. */
+
+typedef void (*XML_StartNamespaceDeclHandler)(void *userData,
+                                              const XML_Char *prefix,
+                                              const XML_Char *uri);
+
+typedef void (*XML_EndNamespaceDeclHandler)(void *userData,
+                                            const XML_Char *prefix);
+
+/* This is called if the document is not standalone (it has an
+external subset or a reference to a parameter entity, but does not
+have standalone="yes"). If this handler returns 0, then processing
+will not continue, and the parser will return a
+XML_ERROR_NOT_STANDALONE error. */
+
+typedef int (*XML_NotStandaloneHandler)(void *userData);
+
+/* This is called for a reference to an external parsed general entity.
+The referenced entity is not automatically parsed.
+The application can parse it immediately or later using
+XML_ExternalEntityParserCreate.
+The parser argument is the parser parsing the entity containing the reference;
+it can be passed as the parser argument to XML_ExternalEntityParserCreate.
+The systemId argument is the system identifier as specified in the entity
+declaration; it will not be null.
+The base argument is the system identifier that should be used as the base for
+resolving systemId if systemId was relative; this is set by XML_SetBase;
+it may be null.
+The publicId argument is the public identifier as specified in the entity
+declaration, or null if none was specified; the whitespace in the public
+identifier will have been normalized as required by the XML spec.
+The context argument specifies the parsing context in the format
+expected by the context argument to
+XML_ExternalEntityParserCreate; context is valid only until the handler
+returns, so if the referenced entity is to be parsed later, it must be copied.
+The handler should return 0 if processing should not continue because of
+a fatal error in the handling of the external entity.
+In this case the calling parser will return an
+XML_ERROR_EXTERNAL_ENTITY_HANDLING error.
+Note that unlike other handlers the first argument is the parser, not
+userData. */
+
+typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser,
+                                            const XML_Char *context,
+                                            const XML_Char *base,
+                                            const XML_Char *systemId,
+                                            const XML_Char *publicId);
+
+/* This structure is filled in by the XML_UnknownEncodingHandler
+to provide information to the parser about encodings that are unknown
+to the parser.
+The map[b] member gives information about byte sequences
+whose first byte is b.
+If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar
+value c.
+If map[b] is -1, then the byte sequence is malformed.
+If map[b] is -n, where n >= 2, then b is the first byte of an n-byte
+sequence that encodes a single Unicode scalar value.
+The data member will be passed as the first argument to the convert function.
+The convert function is used to convert multibyte sequences;
+s will point to a n-byte sequence where map[(unsigned char)*s] == -n.
+The convert function must return the Unicode scalar value
+represented by this byte sequence or -1 if the byte sequence is malformed.
+The convert function may be null if the encoding is a single-byte encoding,
+that is if map[b] >= -1 for all bytes b.
+When the parser is finished with the encoding, then if release is not null,
+it will call release passing it the data member;
+once release has been called, the convert function will not be called again.
+
+Expat places certain restrictions on the encodings that are supported
+using this mechanism.
+
+1. Every ASCII character that can appear in a well-formed XML document,
+other than the characters
+
+  $@\^`{}~
+
+must be represented by a single byte, and that byte must be the
+same byte that represents that character in ASCII.
+
+2. No character may require more than 4 bytes to encode.
+
+3. All characters encoded must have Unicode scalar values <= 0xFFFF, (i.e.,
+characters that would be encoded by surrogates in UTF-16 are  not
+allowed).  Note that this restriction doesn't apply to the built-in
+support for UTF-8 and UTF-16.
+
+4. No Unicode character may be encoded by more than one distinct sequence
+of bytes. */
+
+typedef struct {
+  int map[256];
+  void *data;
+  int (*convert)(void *data, const char *s);
+  void (*release)(void *data);
+} XML_Encoding;
+
+/* This is called for an encoding that is unknown to the parser.
+The encodingHandlerData argument is that which was passed as the
+second argument to XML_SetUnknownEncodingHandler.
+The name argument gives the name of the encoding as specified in
+the encoding declaration.
+If the callback can provide information about the encoding,
+it must fill in the XML_Encoding structure, and return 1.
+Otherwise it must return 0.
+If info does not describe a suitable encoding,
+then the parser will return an XML_UNKNOWN_ENCODING error. */
+
+typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData,
+                                          const XML_Char *name,
+                                          XML_Encoding *info);
+
+XMLPARSEAPI(void)
+XML_SetElementHandler(XML_Parser parser,
+                      XML_StartElementHandler start,
+                      XML_EndElementHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartElementHandler(XML_Parser, XML_StartElementHandler);
+
+XMLPARSEAPI(void)
+XML_SetEndElementHandler(XML_Parser, XML_EndElementHandler);
+
+XMLPARSEAPI(void)
+XML_SetCharacterDataHandler(XML_Parser parser,
+                            XML_CharacterDataHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+                                    XML_ProcessingInstructionHandler handler);
+XMLPARSEAPI(void)
+XML_SetCommentHandler(XML_Parser parser,
+                      XML_CommentHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetCdataSectionHandler(XML_Parser parser,
+                           XML_StartCdataSectionHandler start,
+                           XML_EndCdataSectionHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartCdataSectionHandler(XML_Parser parser,
+                                XML_StartCdataSectionHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndCdataSectionHandler(XML_Parser parser,
+                              XML_EndCdataSectionHandler end);
+
+/* This sets the default handler and also inhibits expansion of
+internal entities.  The entity reference will be passed to the default
+handler. */
+
+XMLPARSEAPI(void)
+XML_SetDefaultHandler(XML_Parser parser,
+                      XML_DefaultHandler handler);
+
+/* This sets the default handler but does not inhibit expansion of
+internal entities.  The entity reference will not be passed to the
+default handler. */
+
+XMLPARSEAPI(void)
+XML_SetDefaultHandlerExpand(XML_Parser parser,
+                            XML_DefaultHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetDoctypeDeclHandler(XML_Parser parser,
+                          XML_StartDoctypeDeclHandler start,
+                          XML_EndDoctypeDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartDoctypeDeclHandler(XML_Parser parser,
+                               XML_StartDoctypeDeclHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndDoctypeDeclHandler(XML_Parser parser,
+                             XML_EndDoctypeDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+                                 XML_UnparsedEntityDeclHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetNotationDeclHandler(XML_Parser parser,
+                           XML_NotationDeclHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetNamespaceDeclHandler(XML_Parser parser,
+                            XML_StartNamespaceDeclHandler start,
+                            XML_EndNamespaceDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetStartNamespaceDeclHandler(XML_Parser parser,
+                                 XML_StartNamespaceDeclHandler start);
+
+XMLPARSEAPI(void)
+XML_SetEndNamespaceDeclHandler(XML_Parser parser,
+                               XML_EndNamespaceDeclHandler end);
+
+XMLPARSEAPI(void)
+XML_SetNotStandaloneHandler(XML_Parser parser,
+                            XML_NotStandaloneHandler handler);
+
+XMLPARSEAPI(void)
+XML_SetExternalEntityRefHandler(XML_Parser parser,
+                                XML_ExternalEntityRefHandler handler);
+
+/* If a non-null value for arg is specified here, then it will be passed
+as the first argument to the external entity ref handler instead
+of the parser object. */
+XMLPARSEAPI(void)
+XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg);
+
+XMLPARSEAPI(void)
+XML_SetUnknownEncodingHandler(XML_Parser parser,
+                              XML_UnknownEncodingHandler handler,
+                              void *encodingHandlerData);
+
+/* This can be called within a handler for a start element, end element,
+processing instruction or character data.  It causes the corresponding
+markup to be passed to the default handler. */
+XMLPARSEAPI(void)
+XML_DefaultCurrent(XML_Parser parser);
+
+/* If do_nst is non-zero, and namespace processing is in effect, and
+   a name has a prefix (i.e. an explicit namespace qualifier) then
+   that name is returned as a triplet in a single
+   string separated by the separator character specified when the parser
+   was created: URI + sep + local_name + sep + prefix.
+
+   If do_nst is zero, then namespace information is returned in the
+   default manner (URI + sep + local_name) whether or not the names
+   has a prefix.
+*/
+
+XMLPARSEAPI(void)
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst);
+
+/* This value is passed as the userData argument to callbacks. */
+XMLPARSEAPI(void)
+XML_SetUserData(XML_Parser parser, void *userData);
+
+/* Returns the last value set by XML_SetUserData or null. */
+#define XML_GetUserData(parser) (*(void **)(parser))
+
+/* This is equivalent to supplying an encoding argument
+to XML_ParserCreate. It must not be called after XML_Parse
+or XML_ParseBuffer. */
+
+XMLPARSEAPI(int)
+XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
+
+/* If this function is called, then the parser will be passed
+as the first argument to callbacks instead of userData.
+The userData will still be accessible using XML_GetUserData. */
+
+XMLPARSEAPI(void)
+XML_UseParserAsHandlerArg(XML_Parser parser);
+
+/* Sets the base to be used for resolving relative URIs in system
+identifiers in declarations.  Resolving relative identifiers is left
+to the application: this value will be passed through as the base
+argument to the XML_ExternalEntityRefHandler, XML_NotationDeclHandler
+and XML_UnparsedEntityDeclHandler. The base argument will be copied.
+Returns zero if out of memory, non-zero otherwise. */
+
+XMLPARSEAPI(int)
+XML_SetBase(XML_Parser parser, const XML_Char *base);
+
+XMLPARSEAPI(const XML_Char *)
+XML_GetBase(XML_Parser parser);
+
+/* Returns the number of the attribute/value pairs passed in last call
+to the XML_StartElementHandler that were specified in the start-tag
+rather than defaulted. Each attribute/value pair counts as 2; thus
+this correspondds to an index into the atts array passed to the
+XML_StartElementHandler. */
+
+XMLPARSEAPI(int)
+XML_GetSpecifiedAttributeCount(XML_Parser parser);
+
+/* Returns the index of the ID attribute passed in the last call to
+XML_StartElementHandler, or -1 if there is no ID attribute.  Each
+attribute/value pair counts as 2; thus this correspondds to an index
+into the atts array passed to the XML_StartElementHandler. */
+
+XMLPARSEAPI(int)
+XML_GetIdAttributeIndex(XML_Parser parser);
+
+/* Parses some input. Returns 0 if a fatal error is detected.
+The last call to XML_Parse must have isFinal true;
+len may be zero for this call (or any other). */
+XMLPARSEAPI(int)
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
+
+XMLPARSEAPI(void *)
+XML_GetBuffer(XML_Parser parser, int len);
+
+XMLPARSEAPI(int)
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
+
+/* Creates an XML_Parser object that can parse an external general
+entity; context is a '\0'-terminated string specifying the parse
+context; encoding is a '\0'-terminated string giving the name of the
+externally specified encoding, or null if there is no externally
+specified encoding.  The context string consists of a sequence of
+tokens separated by formfeeds (\f); a token consisting of a name
+specifies that the general entity of the name is open; a token of the
+form prefix=uri specifies the namespace for a particular prefix; a
+token of the form =uri specifies the default namespace.  This can be
+called at any point after the first call to an
+ExternalEntityRefHandler so longer as the parser has not yet been
+freed.  The new parser is completely independent and may safely be
+used in a separate thread.  The handlers and userData are initialized
+from the parser argument.  Returns 0 if out of memory.  Otherwise
+returns a new XML_Parser object. */
+XMLPARSEAPI(XML_Parser)
+XML_ExternalEntityParserCreate(XML_Parser parser,
+                               const XML_Char *context,
+                               const XML_Char *encoding);
+
+enum XML_ParamEntityParsing {
+  XML_PARAM_ENTITY_PARSING_NEVER,
+  XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE,
+  XML_PARAM_ENTITY_PARSING_ALWAYS
+};
+
+/* Controls parsing of parameter entities (including the external DTD
+subset). If parsing of parameter entities is enabled, then references
+to external parameter entities (including the external DTD subset)
+will be passed to the handler set with
+XML_SetExternalEntityRefHandler.  The context passed will be 0.
+Unlike external general entities, external parameter entities can only
+be parsed synchronously.  If the external parameter entity is to be
+parsed, it must be parsed during the call to the external entity ref
+handler: the complete sequence of XML_ExternalEntityParserCreate,
+XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during
+this call.  After XML_ExternalEntityParserCreate has been called to
+create the parser for the external parameter entity (context must be 0
+for this call), it is illegal to make any calls on the old parser
+until XML_ParserFree has been called on the newly created parser.  If
+the library has been compiled without support for parameter entity
+parsing (ie without XML_DTD being defined), then
+XML_SetParamEntityParsing will return 0 if parsing of parameter
+entities is requested; otherwise it will return non-zero. */
+
+XMLPARSEAPI(int)
+XML_SetParamEntityParsing(XML_Parser parser,
+                          enum XML_ParamEntityParsing parsing);
+
+enum XML_Error {
+  XML_ERROR_NONE,
+  XML_ERROR_NO_MEMORY,
+  XML_ERROR_SYNTAX,
+  XML_ERROR_NO_ELEMENTS,
+  XML_ERROR_INVALID_TOKEN,
+  XML_ERROR_UNCLOSED_TOKEN,
+  XML_ERROR_PARTIAL_CHAR,
+  XML_ERROR_TAG_MISMATCH,
+  XML_ERROR_DUPLICATE_ATTRIBUTE,
+  XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+  XML_ERROR_PARAM_ENTITY_REF,
+  XML_ERROR_UNDEFINED_ENTITY,
+  XML_ERROR_RECURSIVE_ENTITY_REF,
+  XML_ERROR_ASYNC_ENTITY,
+  XML_ERROR_BAD_CHAR_REF,
+  XML_ERROR_BINARY_ENTITY_REF,
+  XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+  XML_ERROR_MISPLACED_XML_PI,
+  XML_ERROR_UNKNOWN_ENCODING,
+  XML_ERROR_INCORRECT_ENCODING,
+  XML_ERROR_UNCLOSED_CDATA_SECTION,
+  XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+  XML_ERROR_NOT_STANDALONE,
+  XML_ERROR_UNEXPECTED_STATE
+};
+
+/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode
+returns information about the error. */
+
+XMLPARSEAPI(enum XML_Error)
+XML_GetErrorCode(XML_Parser parser);
+
+/* These functions return information about the current parse location.
+They may be called when XML_Parse or XML_ParseBuffer return 0;
+in this case the location is the location of the character at which
+the error was detected.
+They may also be called from any other callback called to report
+some parse event; in this the location is the location of the first
+of the sequence of characters that generated the event. */
+
+XMLPARSEAPI(int) XML_GetCurrentLineNumber(XML_Parser parser);
+XMLPARSEAPI(int) XML_GetCurrentColumnNumber(XML_Parser parser);
+XMLPARSEAPI(long) XML_GetCurrentByteIndex(XML_Parser parser);
+
+/* Return the number of bytes in the current event.
+Returns 0 if the event is in an internal entity. */
+
+XMLPARSEAPI(int)
+XML_GetCurrentByteCount(XML_Parser parser);
+
+/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets
+   the integer pointed to by offset to the offset within this buffer
+   of the current parse position, and sets the integer pointed to by size
+   to the size of this buffer (the number of input bytes). Otherwise
+   returns a null pointer. Also returns a null pointer if a parse isn't
+   active.
+
+   NOTE: The character pointer returned should not be used outside
+   the handler that makes the call. */
+
+XMLPARSEAPI(const char *)
+XML_GetInputContext(XML_Parser parser,
+                    int *offset,
+                    int *size);
+
+/* For backwards compatibility with previous versions. */
+#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
+#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
+#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
+
+/* Frees memory used by the parser. */
+XMLPARSEAPI(void)
+XML_ParserFree(XML_Parser parser);
+
+/* Returns a string describing the error. */
+XMLPARSEAPI(const XML_LChar *)
+XML_ErrorString(int code);
+
+/* Return a string containing the version number of this expat */
+XMLPARSEAPI(const XML_LChar *)
+XML_ExpatVersion(void);
+
+typedef struct {
+  int major;
+  int minor;
+  int micro;
+} XML_Expat_Version;
+
+/* Return an XML_Expat_Version structure containing numeric version
+   number information for this version of expat */
+
+XMLPARSEAPI(XML_Expat_Version)
+XML_ExpatVersionInfo(void);
+
+#define XML_MAJOR_VERSION 1
+#define XML_MINOR_VERSION 95
+#define XML_MICRO_VERSION 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlParse_INCLUDED */
diff --git a/Utilities/ITK/Utilities/expat/expatConfig.h.in b/Utilities/ITK/Utilities/expat/expatConfig.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..d6997ec25002cddb4692006e0925a75d3322bd43
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/expatConfig.h.in
@@ -0,0 +1,42 @@
+#if defined(_WIN32) || defined(WIN32)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <memory.h>
+#include <string.h>
+#define XML_BYTE_ORDER 12
+
+#else
+
+#cmakedefine CMAKE_WORDS_BIGENDIAN
+#ifdef CMAKE_WORDS_BIGENDIAN
+#  define XML_BYTE_ORDER 21
+#else
+#  define XML_BYTE_ORDER 12
+#endif
+
+#endif
+
+#define XML_NS
+#define XML_DTD
+#define XML_CONTEXT_BYTES 1024
+
+#if defined ( _MSC_VER )
+#pragma warning ( disable : 4100 )
+#pragma warning ( disable : 4127 )
+#pragma warning ( disable : 4244 )
+#pragma warning ( disable : 4251 )
+#pragma warning ( disable : 4305 )
+#pragma warning ( disable : 4309 )
+#pragma warning ( disable : 4702 )
+#pragma warning ( disable : 4706 )
+#pragma warning ( disable : 4786 )
+#pragma warning ( disable : 4057 )
+#pragma warning ( disable : 4189 )
+#pragma warning ( disable : 4505 )
+#endif
+
+#define VERSION "1.95.2"
+
+#define itkExpatUnused(x) (void)x
diff --git a/Utilities/ITK/Utilities/expat/expatDllConfig.h.in b/Utilities/ITK/Utilities/expat/expatDllConfig.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..7f1986cf85eddad14be06ef6146b43a4d4fc1ad7
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/expatDllConfig.h.in
@@ -0,0 +1,6 @@
+#ifndef _expatDllConfig_h
+#define _expatDllConfig_h
+
+#cmakedefine ITK_EXPAT_STATIC
+
+#endif
diff --git a/Utilities/ITK/Utilities/expat/iasciitab.h b/Utilities/ITK/Utilities/expat/iasciitab.h
new file mode 100644
index 0000000000000000000000000000000000000000..55dbc398b8779da3fbd481b7d61a1dcdaaab189a
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/iasciitab.h
@@ -0,0 +1,38 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
diff --git a/Utilities/ITK/Utilities/expat/latin1tab.h b/Utilities/ITK/Utilities/expat/latin1tab.h
new file mode 100644
index 0000000000000000000000000000000000000000..178b1d186dd1f4015eb899583aa6dfa9c392f50b
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/latin1tab.h
@@ -0,0 +1,37 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
+/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
diff --git a/Utilities/ITK/Utilities/expat/nametab.h b/Utilities/ITK/Utilities/expat/nametab.h
new file mode 100644
index 0000000000000000000000000000000000000000..b05e62c77a6c624a6828dd3f4e25ba8fe841e7a0
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/nametab.h
@@ -0,0 +1,150 @@
+static const unsigned namingBitmap[] = {
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
+0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000,
+0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
+0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003,
+0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003,
+0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
+0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001,
+0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003,
+0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
+0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003,
+0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003,
+0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000,
+0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
+0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF,
+0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB,
+0x40000000, 0xF580C900, 0x00000007, 0x02010800,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF,
+0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
+0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
+0x00000000, 0x00004C40, 0x00000000, 0x00000000,
+0x00000007, 0x00000000, 0x00000000, 0x00000000,
+0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF,
+0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
+0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003,
+0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF,
+0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF,
+0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
+0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF,
+0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0,
+0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
+0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3,
+0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80,
+0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000,
+0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000,
+0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
+0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
+0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
+};
+static const unsigned char nmstrtPages[] = {
+0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,
+0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+static const unsigned char namePages[] = {
+0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00,
+0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
diff --git a/Utilities/ITK/Utilities/expat/utf8tab.h b/Utilities/ITK/Utilities/expat/utf8tab.h
new file mode 100644
index 0000000000000000000000000000000000000000..9e3b6b83eb628ba53b1896ec0279f6cb67630739
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/utf8tab.h
@@ -0,0 +1,38 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+
+/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
+/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
diff --git a/Utilities/ITK/Utilities/expat/xmlparse.c b/Utilities/ITK/Utilities/expat/xmlparse.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d2f72fd10eada49a8dac973da27dd5ebfac6e2c
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/xmlparse.c
@@ -0,0 +1,4622 @@
+/*
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#include "expatConfig.h"
+#include "expat.h"
+
+#include <stddef.h>
+#include <string.h>
+
+#ifdef XML_UNICODE
+#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
+#define XmlConvert XmlUtf16Convert
+#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
+#define XmlEncode XmlUtf16Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
+typedef unsigned short ICHAR;
+#else
+#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
+#define XmlConvert XmlUtf8Convert
+#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
+#define XmlEncode XmlUtf8Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
+typedef char ICHAR;
+#endif
+
+
+#ifndef XML_NS
+
+#define XmlInitEncodingNS XmlInitEncoding
+#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
+#undef XmlGetInternalEncodingNS
+#define XmlGetInternalEncodingNS XmlGetInternalEncoding
+#define XmlParseXmlDeclNS XmlParseXmlDecl
+
+#endif
+
+#ifdef XML_UNICODE_WCHAR_T
+#define XML_T(x) L ## x
+#else
+#define XML_T(x) x
+#endif
+
+/* Round up n to be a multiple of sz, where sz is a power of 2. */
+#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
+
+#include "xmltok.h"
+#include "xmlrole.h"
+
+typedef const XML_Char *KEY;
+
+typedef struct {
+  KEY name;
+} NAMED;
+
+typedef struct {
+  NAMED **v;
+  size_t size;
+  size_t used;
+  size_t usedLim;
+  XML_Memory_Handling_Suite *mem;
+} HASH_TABLE;
+
+typedef struct {
+  NAMED **p;
+  NAMED **end;
+} HASH_TABLE_ITER;
+
+#define INIT_TAG_BUF_SIZE 32  /* must be a multiple of sizeof(XML_Char) */
+#define INIT_DATA_BUF_SIZE 1024
+#define INIT_ATTS_SIZE 16
+#define INIT_BLOCK_SIZE 1024
+#define INIT_BUFFER_SIZE 1024
+
+#define EXPAND_SPARE 24
+
+typedef struct binding {
+  struct prefix *prefix;
+  struct binding *nextTagBinding;
+  struct binding *prevPrefixBinding;
+  const struct attribute_id *attId;
+  XML_Char *uri;
+  int uriLen;
+  int uriAlloc;
+} BINDING;
+
+typedef struct prefix {
+  const XML_Char *name;
+  BINDING *binding;
+} PREFIX;
+
+typedef struct {
+  const XML_Char *str;
+  const XML_Char *localPart;
+  int uriLen;
+} TAG_NAME;
+
+typedef struct tag {
+  struct tag *parent;
+  const char *rawName;
+  int rawNameLength;
+  TAG_NAME name;
+  char *buf;
+  char *bufEnd;
+  BINDING *bindings;
+} TAG;
+
+typedef struct {
+  const XML_Char *name;
+  const XML_Char *textPtr;
+  int textLen;
+  const XML_Char *systemId;
+  const XML_Char *base;
+  const XML_Char *publicId;
+  const XML_Char *notation;
+  char open;
+  char is_param;
+} ENTITY;
+
+typedef struct {
+  enum XML_Content_Type         type;
+  enum XML_Content_Quant        quant;
+  const XML_Char *              name;
+  int                           firstchild;
+  int                           lastchild;
+  int                           childcnt;
+  int                           nextsib;
+} CONTENT_SCAFFOLD;
+
+typedef struct block {
+  struct block *next;
+  int size;
+  XML_Char s[1];
+} BLOCK;
+
+typedef struct {
+  BLOCK *blocks;
+  BLOCK *freeBlocks;
+  const XML_Char *end;
+  XML_Char *ptr;
+  XML_Char *start;
+  XML_Memory_Handling_Suite *mem;
+} STRING_POOL;
+
+/* The XML_Char before the name is used to determine whether
+an attribute has been specified. */
+typedef struct attribute_id {
+  XML_Char *name;
+  PREFIX *prefix;
+  char maybeTokenized;
+  char xmlns;
+} ATTRIBUTE_ID;
+
+typedef struct {
+  const ATTRIBUTE_ID *id;
+  char isCdata;
+  const XML_Char *value;
+} DEFAULT_ATTRIBUTE;
+
+typedef struct {
+  const XML_Char *name;
+  PREFIX *prefix;
+  const ATTRIBUTE_ID *idAtt;
+  int nDefaultAtts;
+  int allocDefaultAtts;
+  DEFAULT_ATTRIBUTE *defaultAtts;
+} ELEMENT_TYPE;
+
+typedef struct {
+  HASH_TABLE generalEntities;
+  HASH_TABLE elementTypes;
+  HASH_TABLE attributeIds;
+  HASH_TABLE prefixes;
+  STRING_POOL pool;
+  int complete;
+  int standalone;
+#ifdef XML_DTD
+  HASH_TABLE paramEntities;
+#endif /* XML_DTD */
+  PREFIX defaultPrefix;
+  /* === scaffolding for building content model === */
+  int in_eldecl;
+  CONTENT_SCAFFOLD *scaffold;
+  unsigned contentStringLen;
+  unsigned scaffSize;
+  unsigned scaffCount;
+  int scaffLevel;
+  int *scaffIndex;
+} DTD;
+
+typedef struct open_internal_entity {
+  const char *internalEventPtr;
+  const char *internalEventEndPtr;
+  struct open_internal_entity *next;
+  ENTITY *entity;
+} OPEN_INTERNAL_ENTITY;
+
+typedef enum XML_Error Processor(XML_Parser parser,
+                                 const char *start,
+                                 const char *end,
+                                 const char **endPtr);
+
+static Processor prologProcessor;
+static Processor prologInitProcessor;
+static Processor contentProcessor;
+static Processor cdataSectionProcessor;
+#ifdef XML_DTD
+static Processor ignoreSectionProcessor;
+#endif /* XML_DTD */
+static Processor epilogProcessor;
+static Processor errorProcessor;
+static Processor externalEntityInitProcessor;
+static Processor externalEntityInitProcessor2;
+static Processor externalEntityInitProcessor3;
+static Processor externalEntityContentProcessor;
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *);
+static enum XML_Error
+initializeEncoding(XML_Parser parser);
+static enum XML_Error
+doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
+         const char *end, int tok, const char *next, const char **nextPtr);
+static enum XML_Error
+processInternalParamEntity(XML_Parser parser, ENTITY *entity);
+static enum XML_Error
+doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
+          const char *start, const char *end, const char **endPtr);
+static enum XML_Error
+doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
+#ifdef XML_DTD
+static enum XML_Error
+doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
+#endif /* XML_DTD */
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s,
+                                TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr);
+
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *,
+                int isCdata, int isId, const XML_Char *dfltValue,
+                XML_Parser parser);
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
+                    STRING_POOL *);
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
+                    STRING_POOL *);
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
+static enum XML_Error
+storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+
+static const XML_Char *getContext(XML_Parser parser);
+static int setContext(XML_Parser parser, const XML_Char *context);
+static void normalizePublicId(XML_Char *s);
+static int dtdInit(DTD *, XML_Parser parser);
+
+static void dtdDestroy(DTD *, XML_Parser parser);
+
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd, XML_Parser parser);
+
+static int copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *,
+                           XML_Parser parser);
+
+#ifdef XML_DTD
+static void dtdSwap(DTD *, DTD *);
+#endif /* XML_DTD */
+
+static NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize);
+
+static void hashTableInit(HASH_TABLE *, XML_Memory_Handling_Suite *ms);
+
+static void hashTableDestroy(HASH_TABLE *);
+static void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
+static NAMED *hashTableIterNext(HASH_TABLE_ITER *);
+static void poolInit(STRING_POOL *, XML_Memory_Handling_Suite *ms);
+static void poolClear(STRING_POOL *);
+static void poolDestroy(STRING_POOL *);
+static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+                            const char *ptr, const char *end);
+static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+                                  const char *ptr, const char *end);
+
+static int poolGrow(STRING_POOL *pool);
+
+static int nextScaffoldPart(XML_Parser parser);
+static XML_Content *build_model(XML_Parser parser);
+
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
+static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
+static const XML_Char *poolAppendString(STRING_POOL *pool, const XML_Char *s);
+static ELEMENT_TYPE * getElementType(XML_Parser Paraser,
+                                     const ENCODING *enc,
+                                     const char *ptr,
+                                     const char *end);
+
+#define poolStart(pool) ((pool)->start)
+#define poolEnd(pool) ((pool)->ptr)
+#define poolLength(pool) ((pool)->ptr - (pool)->start)
+#define poolChop(pool) ((void)--(pool->ptr))
+#define poolLastChar(pool) (((pool)->ptr)[-1])
+#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
+#define poolFinish(pool) ((pool)->start = (pool)->ptr)
+#define poolAppendChar(pool, c) \
+  (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
+   ? 0 \
+   : ((*((pool)->ptr)++ = c), 1))
+
+typedef struct {
+  /* The first member must be userData so that the XML_GetUserData macro works. */
+  void *m_userData;
+  void *m_handlerArg;
+  char *m_buffer;
+  XML_Memory_Handling_Suite m_mem;
+  /* first character to be parsed */
+  const char *m_bufferPtr;
+  /* past last character to be parsed */
+  char *m_bufferEnd;
+  /* allocated end of buffer */
+  const char *m_bufferLim;
+  long m_parseEndByteIndex;
+  const char *m_parseEndPtr;
+  XML_Char *m_dataBuf;
+  XML_Char *m_dataBufEnd;
+  XML_StartElementHandler m_startElementHandler;
+  XML_EndElementHandler m_endElementHandler;
+  XML_CharacterDataHandler m_characterDataHandler;
+  XML_ProcessingInstructionHandler m_processingInstructionHandler;
+  XML_CommentHandler m_commentHandler;
+  XML_StartCdataSectionHandler m_startCdataSectionHandler;
+  XML_EndCdataSectionHandler m_endCdataSectionHandler;
+  XML_DefaultHandler m_defaultHandler;
+  XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
+  XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
+  XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
+  XML_NotationDeclHandler m_notationDeclHandler;
+  XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
+  XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
+  XML_NotStandaloneHandler m_notStandaloneHandler;
+  XML_ExternalEntityRefHandler m_externalEntityRefHandler;
+  void *m_externalEntityRefHandlerArg;
+  XML_UnknownEncodingHandler m_unknownEncodingHandler;
+  XML_ElementDeclHandler m_elementDeclHandler;
+  XML_AttlistDeclHandler m_attlistDeclHandler;
+  XML_EntityDeclHandler m_entityDeclHandler;
+  XML_XmlDeclHandler m_xmlDeclHandler;
+  const ENCODING *m_encoding;
+  INIT_ENCODING m_initEncoding;
+  const ENCODING *m_internalEncoding;
+  const XML_Char *m_protocolEncodingName;
+  int m_ns;
+  int m_ns_triplets;
+  void *m_unknownEncodingMem;
+  void *m_unknownEncodingData;
+  void *m_unknownEncodingHandlerData;
+  void (*m_unknownEncodingRelease)(void *);
+  PROLOG_STATE m_prologState;
+  Processor *m_processor;
+  enum XML_Error m_errorCode;
+  const char *m_eventPtr;
+  const char *m_eventEndPtr;
+  const char *m_positionPtr;
+  OPEN_INTERNAL_ENTITY *m_openInternalEntities;
+  int m_defaultExpandInternalEntities;
+  int m_tagLevel;
+  ENTITY *m_declEntity;
+  const XML_Char *m_doctypeName;
+  const XML_Char *m_doctypeSysid;
+  const XML_Char *m_doctypePubid;
+  const XML_Char *m_declAttributeType;
+  const XML_Char *m_declNotationName;
+  const XML_Char *m_declNotationPublicId;
+  ELEMENT_TYPE *m_declElementType;
+  ATTRIBUTE_ID *m_declAttributeId;
+  char m_declAttributeIsCdata;
+  char m_declAttributeIsId;
+  DTD m_dtd;
+  const XML_Char *m_curBase;
+  TAG *m_tagStack;
+  TAG *m_freeTagList;
+  BINDING *m_inheritedBindings;
+  BINDING *m_freeBindingList;
+  int m_attsSize;
+  int m_nSpecifiedAtts;
+  int m_idAttIndex;
+  ATTRIBUTE *m_atts;
+  POSITION m_position;
+  STRING_POOL m_tempPool;
+  STRING_POOL m_temp2Pool;
+  char *m_groupConnector;
+  unsigned m_groupSize;
+  int m_hadExternalDoctype;
+  XML_Char m_namespaceSeparator;
+#ifdef XML_DTD
+  enum XML_ParamEntityParsing m_paramEntityParsing;
+  XML_Parser m_parentParser;
+#endif
+} Parser;
+
+#define MALLOC(s) (((Parser *)parser)->m_mem.malloc_fcn((s)))
+#define REALLOC(p,s) (((Parser *)parser)->m_mem.realloc_fcn((p),(s)))
+#define FREE(p) (((Parser *)parser)->m_mem.free_fcn((p)))
+
+#define userData (((Parser *)parser)->m_userData)
+#define handlerArg (((Parser *)parser)->m_handlerArg)
+#define startElementHandler (((Parser *)parser)->m_startElementHandler)
+#define endElementHandler (((Parser *)parser)->m_endElementHandler)
+#define characterDataHandler (((Parser *)parser)->m_characterDataHandler)
+#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler)
+#define commentHandler (((Parser *)parser)->m_commentHandler)
+#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler)
+#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler)
+#define defaultHandler (((Parser *)parser)->m_defaultHandler)
+#define startDoctypeDeclHandler (((Parser *)parser)->m_startDoctypeDeclHandler)
+#define endDoctypeDeclHandler (((Parser *)parser)->m_endDoctypeDeclHandler)
+#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler)
+#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler)
+#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler)
+#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler)
+#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler)
+#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler)
+#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg)
+#define internalEntityRefHandler (((Parser *)parser)->m_internalEntityRefHandler)
+#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler)
+#define elementDeclHandler (((Parser *)parser)->m_elementDeclHandler)
+#define attlistDeclHandler (((Parser *)parser)->m_attlistDeclHandler)
+#define entityDeclHandler (((Parser *)parser)->m_entityDeclHandler)
+#define xmlDeclHandler (((Parser *)parser)->m_xmlDeclHandler)
+#define encoding (((Parser *)parser)->m_encoding)
+#define initEncoding (((Parser *)parser)->m_initEncoding)
+#define internalEncoding (((Parser *)parser)->m_internalEncoding)
+#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem)
+#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData)
+#define unknownEncodingHandlerData \
+  (((Parser *)parser)->m_unknownEncodingHandlerData)
+#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease)
+#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName)
+#define ns (((Parser *)parser)->m_ns)
+#define ns_triplets (((Parser *)parser)->m_ns_triplets)
+#define prologState (((Parser *)parser)->m_prologState)
+#define processor (((Parser *)parser)->m_processor)
+#define errorCode (((Parser *)parser)->m_errorCode)
+#define eventPtr (((Parser *)parser)->m_eventPtr)
+#define eventEndPtr (((Parser *)parser)->m_eventEndPtr)
+#define positionPtr (((Parser *)parser)->m_positionPtr)
+#define position (((Parser *)parser)->m_position)
+#define openInternalEntities (((Parser *)parser)->m_openInternalEntities)
+#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities)
+#define tagLevel (((Parser *)parser)->m_tagLevel)
+#define buffer (((Parser *)parser)->m_buffer)
+#define bufferPtr (((Parser *)parser)->m_bufferPtr)
+#define bufferEnd (((Parser *)parser)->m_bufferEnd)
+#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex)
+#define parseEndPtr (((Parser *)parser)->m_parseEndPtr)
+#define bufferLim (((Parser *)parser)->m_bufferLim)
+#define dataBuf (((Parser *)parser)->m_dataBuf)
+#define dataBufEnd (((Parser *)parser)->m_dataBufEnd)
+#define dtd (((Parser *)parser)->m_dtd)
+#define curBase (((Parser *)parser)->m_curBase)
+#define declEntity (((Parser *)parser)->m_declEntity)
+#define doctypeName (((Parser *)parser)->m_doctypeName)
+#define doctypeSysid (((Parser *)parser)->m_doctypeSysid)
+#define doctypePubid (((Parser *)parser)->m_doctypePubid)
+#define declAttributeType (((Parser *)parser)->m_declAttributeType)
+#define declNotationName (((Parser *)parser)->m_declNotationName)
+#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId)
+#define declElementType (((Parser *)parser)->m_declElementType)
+#define declAttributeId (((Parser *)parser)->m_declAttributeId)
+#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata)
+#define declAttributeIsId (((Parser *)parser)->m_declAttributeIsId)
+#define freeTagList (((Parser *)parser)->m_freeTagList)
+#define freeBindingList (((Parser *)parser)->m_freeBindingList)
+#define inheritedBindings (((Parser *)parser)->m_inheritedBindings)
+#define tagStack (((Parser *)parser)->m_tagStack)
+#define atts (((Parser *)parser)->m_atts)
+#define attsSize (((Parser *)parser)->m_attsSize)
+#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts)
+#define idAttIndex (((Parser *)parser)->m_idAttIndex)
+#define tempPool (((Parser *)parser)->m_tempPool)
+#define temp2Pool (((Parser *)parser)->m_temp2Pool)
+#define groupConnector (((Parser *)parser)->m_groupConnector)
+#define groupSize (((Parser *)parser)->m_groupSize)
+#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype)
+#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator)
+#ifdef XML_DTD
+#define parentParser (((Parser *)parser)->m_parentParser)
+#define paramEntityParsing (((Parser *)parser)->m_paramEntityParsing)
+#endif /* XML_DTD */
+
+#ifdef COMPILED_FROM_DSP
+BOOL WINAPI DllMain(HINSTANCE h, DWORD r, LPVOID p) {
+  return TRUE;
+}
+#endif /* def COMPILED_FROM_DSP */
+
+#ifdef _MSC_VER
+#ifdef _DEBUG
+Parser *asParser(XML_Parser parser)
+{
+  return parser;
+}
+#endif
+#endif
+
+XML_Parser XML_ParserCreate(const XML_Char *encodingName)
+{
+  return XML_ParserCreate_MM(encodingName, NULL, NULL);
+}
+
+XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
+{
+  XML_Char tmp[2];
+  *tmp = nsSep;
+  return XML_ParserCreate_MM(encodingName, NULL, tmp);
+}
+
+XML_Parser
+XML_ParserCreate_MM(const XML_Char *encodingName,
+                    const XML_Memory_Handling_Suite *memsuite,
+                    const XML_Char *nameSep) {
+  
+  XML_Parser parser;
+  static
+  const XML_Char implicitContext[] = {
+    XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='),
+    XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'),
+    XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'),
+    XML_T('.'), XML_T('w'), XML_T('3'),
+    XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'),
+    XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'),
+    XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'),
+    XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'),
+    XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'),
+    XML_T('\0')
+  };
+
+
+  if (memsuite) {
+    XML_Memory_Handling_Suite *mtemp;
+    parser = memsuite->malloc_fcn(sizeof(Parser));
+    mtemp = &(((Parser *) parser)->m_mem);
+    mtemp->malloc_fcn = memsuite->malloc_fcn;
+    mtemp->realloc_fcn = memsuite->realloc_fcn;
+    mtemp->free_fcn = memsuite->free_fcn;
+  }
+  else {
+    XML_Memory_Handling_Suite *mtemp;
+    parser = malloc(sizeof(Parser));
+    mtemp = &(((Parser *) parser)->m_mem);
+    mtemp->malloc_fcn = malloc;
+    mtemp->realloc_fcn = realloc;
+    mtemp->free_fcn = free;
+  }
+
+  if (!parser)
+    return parser;
+  processor = prologInitProcessor;
+  XmlPrologStateInit(&prologState);
+  userData = 0;
+  handlerArg = 0;
+  startElementHandler = 0;
+  endElementHandler = 0;
+  characterDataHandler = 0;
+  processingInstructionHandler = 0;
+  commentHandler = 0;
+  startCdataSectionHandler = 0;
+  endCdataSectionHandler = 0;
+  defaultHandler = 0;
+  startDoctypeDeclHandler = 0;
+  endDoctypeDeclHandler = 0;
+  unparsedEntityDeclHandler = 0;
+  notationDeclHandler = 0;
+  startNamespaceDeclHandler = 0;
+  endNamespaceDeclHandler = 0;
+  notStandaloneHandler = 0;
+  externalEntityRefHandler = 0;
+  externalEntityRefHandlerArg = parser;
+  unknownEncodingHandler = 0;
+  elementDeclHandler = 0;
+  attlistDeclHandler = 0;
+  entityDeclHandler = 0;
+  xmlDeclHandler = 0;
+  buffer = 0;
+  bufferPtr = 0;
+  bufferEnd = 0;
+  parseEndByteIndex = 0;
+  parseEndPtr = 0;
+  bufferLim = 0;
+  declElementType = 0;
+  declAttributeId = 0;
+  declEntity = 0;
+  doctypeName = 0;
+  doctypeSysid = 0;
+  doctypePubid = 0;
+  declAttributeType = 0;
+  declNotationName = 0;
+  declNotationPublicId = 0;
+  memset(&position, 0, sizeof(POSITION));
+  errorCode = XML_ERROR_NONE;
+  eventPtr = 0;
+  eventEndPtr = 0;
+  positionPtr = 0;
+  openInternalEntities = 0;
+  tagLevel = 0;
+  tagStack = 0;
+  freeTagList = 0;
+  freeBindingList = 0;
+  inheritedBindings = 0;
+  attsSize = INIT_ATTS_SIZE;
+  atts = MALLOC(attsSize * sizeof(ATTRIBUTE));
+  nSpecifiedAtts = 0;
+  dataBuf = MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
+  groupSize = 0;
+  groupConnector = 0;
+  hadExternalDoctype = 0;
+  unknownEncodingMem = 0;
+  unknownEncodingRelease = 0;
+  unknownEncodingData = 0;
+  unknownEncodingHandlerData = 0;
+  namespaceSeparator = '!';
+#ifdef XML_DTD
+  parentParser = 0;
+  paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+#endif
+  ns = 0;
+  ns_triplets = 0;
+  poolInit(&tempPool, &(((Parser *) parser)->m_mem));
+  poolInit(&temp2Pool, &(((Parser *) parser)->m_mem));
+  protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0;
+  curBase = 0;
+  if (!dtdInit(&dtd, parser) || !atts || !dataBuf
+      || (encodingName && !protocolEncodingName)) {
+    XML_ParserFree(parser);
+    return 0;
+  }
+  dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
+
+  if (nameSep) {
+    XmlInitEncodingNS(&initEncoding, &encoding, 0);
+    ns = 1;
+    internalEncoding = XmlGetInternalEncodingNS();
+    namespaceSeparator = *nameSep;
+
+    if (! setContext(parser, implicitContext)) {
+      XML_ParserFree(parser);
+      return 0;
+    }
+  }
+  else {
+    XmlInitEncoding(&initEncoding, &encoding, 0);
+    internalEncoding = XmlGetInternalEncoding();
+  }
+
+  return parser;
+}  /* End XML_ParserCreate_MM */
+
+int XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+  if (!encodingName)
+    protocolEncodingName = 0;
+  else {
+    protocolEncodingName = poolCopyString(&tempPool, encodingName);
+    if (!protocolEncodingName)
+      return 0;
+  }
+  return 1;
+}
+
+XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser,
+                                          const XML_Char *context,
+                                          const XML_Char *encodingName)
+{
+  XML_Parser parser = oldParser;
+  DTD *oldDtd = &dtd;
+  XML_StartElementHandler oldStartElementHandler = startElementHandler;
+  XML_EndElementHandler oldEndElementHandler = endElementHandler;
+  XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
+  XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler;
+  XML_CommentHandler oldCommentHandler = commentHandler;
+  XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler;
+  XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler;
+  XML_DefaultHandler oldDefaultHandler = defaultHandler;
+  XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
+  XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
+  XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
+  XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
+  XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
+  XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler;
+  XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler;
+  XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
+  XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
+  XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
+  XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
+  ELEMENT_TYPE * oldDeclElementType = declElementType;
+
+  void *oldUserData = userData;
+  void *oldHandlerArg = handlerArg;
+  int oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
+  void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+#ifdef XML_DTD
+  enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
+#endif
+  int oldns_triplets = ns_triplets;
+
+  if (ns) {
+    XML_Char tmp[2];
+
+    *tmp = namespaceSeparator;
+    parser = XML_ParserCreate_MM(encodingName, &((Parser *)parser)->m_mem,
+                                 tmp);
+  }
+  else {
+    parser = XML_ParserCreate_MM(encodingName, &((Parser *)parser)->m_mem,
+                                 NULL);
+  }
+
+  if (!parser)
+    return 0;
+
+  startElementHandler = oldStartElementHandler;
+  endElementHandler = oldEndElementHandler;
+  characterDataHandler = oldCharacterDataHandler;
+  processingInstructionHandler = oldProcessingInstructionHandler;
+  commentHandler = oldCommentHandler;
+  startCdataSectionHandler = oldStartCdataSectionHandler;
+  endCdataSectionHandler = oldEndCdataSectionHandler;
+  defaultHandler = oldDefaultHandler;
+  unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
+  notationDeclHandler = oldNotationDeclHandler;
+  startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
+  endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
+  notStandaloneHandler = oldNotStandaloneHandler;
+  externalEntityRefHandler = oldExternalEntityRefHandler;
+  unknownEncodingHandler = oldUnknownEncodingHandler;
+  elementDeclHandler = oldElementDeclHandler;
+  attlistDeclHandler = oldAttlistDeclHandler;
+  entityDeclHandler = oldEntityDeclHandler;
+  xmlDeclHandler = oldXmlDeclHandler;
+  declElementType = oldDeclElementType;
+  userData = oldUserData;
+  if (oldUserData == oldHandlerArg)
+    handlerArg = userData;
+  else
+    handlerArg = parser;
+  if (oldExternalEntityRefHandlerArg != oldParser)
+    externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+  defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+  ns_triplets = oldns_triplets;
+#ifdef XML_DTD
+  paramEntityParsing = oldParamEntityParsing;
+  if (context) {
+#endif /* XML_DTD */
+    if (!dtdCopy(&dtd, oldDtd, parser) || !setContext(parser, context)) {
+      XML_ParserFree(parser);
+      return 0;
+    }
+    processor = externalEntityInitProcessor;
+#ifdef XML_DTD
+  }
+  else {
+    dtdSwap(&dtd, oldDtd);
+    parentParser = oldParser;
+    XmlPrologStateInitExternalEntity(&prologState);
+    dtd.complete = 1;
+    hadExternalDoctype = 1;
+  }
+#endif /* XML_DTD */
+  return parser;
+}
+
+static
+void destroyBindings(BINDING *bindings, XML_Parser parser)
+{
+  for (;;) {
+    BINDING *b = bindings;
+    if (!b)
+      break;
+    bindings = b->nextTagBinding;
+    FREE(b->uri);
+    FREE(b);
+  }
+}
+
+void XML_ParserFree(XML_Parser parser)
+{
+  for (;;) {
+    TAG *p;
+    if (tagStack == 0) {
+      if (freeTagList == 0)
+        break;
+      tagStack = freeTagList;
+      freeTagList = 0;
+    }
+    p = tagStack;
+    tagStack = tagStack->parent;
+    FREE(p->buf);
+    destroyBindings(p->bindings, parser);
+    FREE(p);
+  }
+  destroyBindings(freeBindingList, parser);
+  destroyBindings(inheritedBindings, parser);
+  poolDestroy(&tempPool);
+  poolDestroy(&temp2Pool);
+#ifdef XML_DTD
+  if (parentParser) {
+    if (hadExternalDoctype)
+      dtd.complete = 0;
+    dtdSwap(&dtd, &((Parser *)parentParser)->m_dtd);
+  }
+#endif /* XML_DTD */
+  dtdDestroy(&dtd, parser);
+  FREE((void *)atts);
+  if (groupConnector)
+    FREE(groupConnector);
+  if (buffer)
+    FREE(buffer);
+  FREE(dataBuf);
+  if (unknownEncodingMem)
+    FREE(unknownEncodingMem);
+  if (unknownEncodingRelease)
+    unknownEncodingRelease(unknownEncodingData);
+  FREE(parser);
+}
+
+void XML_UseParserAsHandlerArg(XML_Parser parser)
+{
+  handlerArg = parser;
+}
+
+void
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {
+  ns_triplets = do_nst;
+}
+
+void XML_SetUserData(XML_Parser parser, void *p)
+{
+  if (handlerArg == userData)
+    handlerArg = userData = p;
+  else
+    userData = p;
+}
+
+int XML_SetBase(XML_Parser parser, const XML_Char *p)
+{
+  if (p) {
+    p = poolCopyString(&dtd.pool, p);
+    if (!p)
+      return 0;
+    curBase = p;
+  }
+  else
+    curBase = 0;
+  return 1;
+}
+
+const XML_Char *XML_GetBase(XML_Parser parser)
+{
+  return curBase;
+}
+
+int XML_GetSpecifiedAttributeCount(XML_Parser parser)
+{
+  return nSpecifiedAtts;
+}
+
+int XML_GetIdAttributeIndex(XML_Parser parser)
+{
+  return idAttIndex;
+}
+
+void XML_SetElementHandler(XML_Parser parser,
+                           XML_StartElementHandler start,
+                           XML_EndElementHandler end)
+{
+  startElementHandler = start;
+  endElementHandler = end;
+}
+
+void XML_SetStartElementHandler(XML_Parser parser,
+                                XML_StartElementHandler start) {
+  startElementHandler = start;
+}
+
+void XML_SetEndElementHandler(XML_Parser parser,
+                              XML_EndElementHandler end) {
+  endElementHandler = end;
+}
+
+void XML_SetCharacterDataHandler(XML_Parser parser,
+                                 XML_CharacterDataHandler handler)
+{
+  characterDataHandler = handler;
+}
+
+void XML_SetProcessingInstructionHandler(XML_Parser parser,
+                                         XML_ProcessingInstructionHandler handler)
+{
+  processingInstructionHandler = handler;
+}
+
+void XML_SetCommentHandler(XML_Parser parser,
+                           XML_CommentHandler handler)
+{
+  commentHandler = handler;
+}
+
+void XML_SetCdataSectionHandler(XML_Parser parser,
+                                XML_StartCdataSectionHandler start,
+                                XML_EndCdataSectionHandler end)
+{
+  startCdataSectionHandler = start;
+  endCdataSectionHandler = end;
+}
+
+void XML_SetStartCdataSectionHandler(XML_Parser parser,
+                                     XML_StartCdataSectionHandler start) {
+  startCdataSectionHandler = start;
+}
+
+void XML_SetEndCdataSectionHandler(XML_Parser parser,
+                                   XML_EndCdataSectionHandler end) {
+  endCdataSectionHandler = end;
+}
+
+void XML_SetDefaultHandler(XML_Parser parser,
+                           XML_DefaultHandler handler)
+{
+  defaultHandler = handler;
+  defaultExpandInternalEntities = 0;
+}
+
+void XML_SetDefaultHandlerExpand(XML_Parser parser,
+                                 XML_DefaultHandler handler)
+{
+  defaultHandler = handler;
+  defaultExpandInternalEntities = 1;
+}
+
+void XML_SetDoctypeDeclHandler(XML_Parser parser,
+                               XML_StartDoctypeDeclHandler start,
+                               XML_EndDoctypeDeclHandler end)
+{
+  startDoctypeDeclHandler = start;
+  endDoctypeDeclHandler = end;
+}
+
+void XML_SetStartDoctypeDeclHandler(XML_Parser parser,
+                                    XML_StartDoctypeDeclHandler start) {
+  startDoctypeDeclHandler = start;
+}
+
+void XML_SetEndDoctypeDeclHandler(XML_Parser parser,
+                                  XML_EndDoctypeDeclHandler end) {
+  endDoctypeDeclHandler = end;
+}
+
+void XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+                                      XML_UnparsedEntityDeclHandler handler)
+{
+  unparsedEntityDeclHandler = handler;
+}
+
+void XML_SetNotationDeclHandler(XML_Parser parser,
+                                XML_NotationDeclHandler handler)
+{
+  notationDeclHandler = handler;
+}
+
+void XML_SetNamespaceDeclHandler(XML_Parser parser,
+                                 XML_StartNamespaceDeclHandler start,
+                                 XML_EndNamespaceDeclHandler end)
+{
+  startNamespaceDeclHandler = start;
+  endNamespaceDeclHandler = end;
+}
+
+void XML_SetStartNamespaceDeclHandler(XML_Parser parser,
+                                      XML_StartNamespaceDeclHandler start) {
+  startNamespaceDeclHandler = start;
+}
+
+void XML_SetEndNamespaceDeclHandler(XML_Parser parser,
+                                    XML_EndNamespaceDeclHandler end) {
+  endNamespaceDeclHandler = end;
+}
+
+
+void XML_SetNotStandaloneHandler(XML_Parser parser,
+                                 XML_NotStandaloneHandler handler)
+{
+  notStandaloneHandler = handler;
+}
+
+void XML_SetExternalEntityRefHandler(XML_Parser parser,
+                                     XML_ExternalEntityRefHandler handler)
+{
+  externalEntityRefHandler = handler;
+}
+
+void XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
+{
+  if (arg)
+    externalEntityRefHandlerArg = arg;
+  else
+    externalEntityRefHandlerArg = parser;
+}
+
+void XML_SetUnknownEncodingHandler(XML_Parser parser,
+                                   XML_UnknownEncodingHandler handler,
+                                   void *data)
+{
+  unknownEncodingHandler = handler;
+  unknownEncodingHandlerData = data;
+}
+
+void XML_SetElementDeclHandler(XML_Parser parser,
+                               XML_ElementDeclHandler eldecl)
+{
+  elementDeclHandler = eldecl;
+}
+
+void XML_SetAttlistDeclHandler(XML_Parser parser,
+                               XML_AttlistDeclHandler attdecl)
+{
+  attlistDeclHandler = attdecl;
+}
+
+void XML_SetEntityDeclHandler(XML_Parser parser,
+                              XML_EntityDeclHandler handler)
+{
+  entityDeclHandler = handler;
+}
+
+void XML_SetXmlDeclHandler(XML_Parser parser,
+                           XML_XmlDeclHandler handler) {
+  xmlDeclHandler = handler;
+}
+
+int XML_SetParamEntityParsing(XML_Parser parser,
+                              enum XML_ParamEntityParsing parsing)
+{
+#ifdef XML_DTD
+  paramEntityParsing = parsing;
+  return 1;
+#else
+  return parsing == XML_PARAM_ENTITY_PARSING_NEVER;
+#endif
+}
+
+int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
+{
+  if (len == 0) {
+    if (!isFinal)
+      return 1;
+    positionPtr = bufferPtr;
+    errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
+    if (errorCode == XML_ERROR_NONE)
+      return 1;
+    eventEndPtr = eventPtr;
+    processor = errorProcessor;
+    return 0;
+  }
+#ifndef XML_CONTEXT_BYTES
+  else if (bufferPtr == bufferEnd) {
+    const char *end;
+    int nLeftOver;
+    parseEndByteIndex += len;
+    positionPtr = s;
+    if (isFinal) {
+      errorCode = processor(parser, s, parseEndPtr = s + len, 0);
+      if (errorCode == XML_ERROR_NONE)
+        return 1;
+      eventEndPtr = eventPtr;
+      processor = errorProcessor;
+      return 0;
+    }
+    errorCode = processor(parser, s, parseEndPtr = s + len, &end);
+    if (errorCode != XML_ERROR_NONE) {
+      eventEndPtr = eventPtr;
+      processor = errorProcessor;
+      return 0;
+    }
+    XmlUpdatePosition(encoding, positionPtr, end, &position);
+    nLeftOver = s + len - end;
+    if (nLeftOver) {
+      if (buffer == 0 || nLeftOver > bufferLim - buffer) {
+        /* FIXME avoid integer overflow */
+        buffer = buffer == 0 ? MALLOC(len * 2) : REALLOC(buffer, len * 2);
+        /* FIXME storage leak if realloc fails */
+        if (!buffer) {
+          errorCode = XML_ERROR_NO_MEMORY;
+          eventPtr = eventEndPtr = 0;
+          processor = errorProcessor;
+          return 0;
+        }
+        bufferLim = buffer + len * 2;
+      }
+      memcpy(buffer, end, nLeftOver);
+      bufferPtr = buffer;
+      bufferEnd = buffer + nLeftOver;
+    }
+    return 1;
+  }
+#endif  /* not defined XML_CONTEXT_BYTES */
+  else {
+    memcpy(XML_GetBuffer(parser, len), s, len);
+    return XML_ParseBuffer(parser, len, isFinal);
+  }
+}
+
+int XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
+{
+  const char *start = bufferPtr;
+  positionPtr = start;
+  bufferEnd += len;
+  parseEndByteIndex += len;
+  errorCode = processor(parser, start, parseEndPtr = bufferEnd,
+                        isFinal ? (const char **)0 : &bufferPtr);
+  if (errorCode == XML_ERROR_NONE) {
+    if (!isFinal)
+      XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+    return 1;
+  }
+  else {
+    eventEndPtr = eventPtr;
+    processor = errorProcessor;
+    return 0;
+  }
+}
+
+void *XML_GetBuffer(XML_Parser parser, int len)
+{
+  if (len > bufferLim - bufferEnd) {
+    /* FIXME avoid integer overflow */
+    int neededSize = len + (bufferEnd - bufferPtr);
+#ifdef XML_CONTEXT_BYTES
+    int keep = bufferPtr - buffer;
+
+    if (keep > XML_CONTEXT_BYTES)
+      keep = XML_CONTEXT_BYTES;
+    neededSize += keep;
+#endif  /* defined XML_CONTEXT_BYTES */
+    if (neededSize  <= bufferLim - buffer) {
+#ifdef XML_CONTEXT_BYTES
+      if (keep < bufferPtr - buffer) {
+        int offset = (bufferPtr - buffer) - keep;
+        memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
+        bufferEnd -= offset;
+        bufferPtr -= offset;
+      }
+#else
+      memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
+      bufferEnd = buffer + (bufferEnd - bufferPtr);
+      bufferPtr = buffer;
+#endif  /* not defined XML_CONTEXT_BYTES */
+    }
+    else {
+      char *newBuf;
+      int bufferSize = bufferLim - bufferPtr;
+      if (bufferSize == 0)
+        bufferSize = INIT_BUFFER_SIZE;
+      do {
+        bufferSize *= 2;
+      } while (bufferSize < neededSize);
+      newBuf = MALLOC(bufferSize);
+      if (newBuf == 0) {
+        errorCode = XML_ERROR_NO_MEMORY;
+        return 0;
+      }
+      bufferLim = newBuf + bufferSize;
+#ifdef XML_CONTEXT_BYTES
+      if (bufferPtr) {
+        int keep = bufferPtr - buffer;
+        if (keep > XML_CONTEXT_BYTES)
+          keep = XML_CONTEXT_BYTES;
+        memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
+        FREE(buffer);
+        buffer = newBuf;
+        bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
+        bufferPtr = buffer + keep;
+      }
+      else {
+        bufferEnd = newBuf + (bufferEnd - bufferPtr);
+        bufferPtr = buffer = newBuf;
+      }
+#else
+      if (bufferPtr) {
+        memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
+        FREE(buffer);
+      }
+      bufferEnd = newBuf + (bufferEnd - bufferPtr);
+      bufferPtr = buffer = newBuf;
+#endif  /* not defined XML_CONTEXT_BYTES */
+    }
+  }
+  return bufferEnd;
+}
+
+enum XML_Error XML_GetErrorCode(XML_Parser parser)
+{
+  return errorCode;
+}
+
+long XML_GetCurrentByteIndex(XML_Parser parser)
+{
+  if (eventPtr)
+    return parseEndByteIndex - (parseEndPtr - eventPtr);
+  return -1;
+}
+
+int XML_GetCurrentByteCount(XML_Parser parser)
+{
+  if (eventEndPtr && eventPtr)
+    return eventEndPtr - eventPtr;
+  return 0;
+}
+
+const char * XML_GetInputContext(XML_Parser parser, int *offset, int *size)
+{
+#ifdef XML_CONTEXT_BYTES
+  if (eventPtr && buffer) {
+    *offset = eventPtr - buffer;
+    *size   = bufferEnd - buffer;
+    return buffer;
+  }
+#endif /* defined XML_CONTEXT_BYTES */
+  return (char *) 0;
+}
+
+int XML_GetCurrentLineNumber(XML_Parser parser)
+{
+  if (eventPtr) {
+    XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+    positionPtr = eventPtr;
+  }
+  return position.lineNumber + 1;
+}
+
+int XML_GetCurrentColumnNumber(XML_Parser parser)
+{
+  if (eventPtr) {
+    XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+    positionPtr = eventPtr;
+  }
+  return position.columnNumber;
+}
+
+void XML_DefaultCurrent(XML_Parser parser)
+{
+  if (defaultHandler) {
+    if (openInternalEntities)
+      reportDefault(parser,
+                    internalEncoding,
+                    openInternalEntities->internalEventPtr,
+                    openInternalEntities->internalEventEndPtr);
+    else
+      reportDefault(parser, encoding, eventPtr, eventEndPtr);
+  }
+}
+
+const XML_LChar *XML_ErrorString(int code)
+{
+  static const XML_LChar *message[] = {
+    0,
+    XML_T("out of memory"),
+    XML_T("syntax error"),
+    XML_T("no element found"),
+    XML_T("not well-formed (invalid token)"),
+    XML_T("unclosed token"),
+    XML_T("unclosed token"),
+    XML_T("mismatched tag"),
+    XML_T("duplicate attribute"),
+    XML_T("junk after document element"),
+    XML_T("illegal parameter entity reference"),
+    XML_T("undefined entity"),
+    XML_T("recursive entity reference"),
+    XML_T("asynchronous entity"),
+    XML_T("reference to invalid character number"),
+    XML_T("reference to binary entity"),
+    XML_T("reference to external entity in attribute"),
+    XML_T("xml processing instruction not at start of external entity"),
+    XML_T("unknown encoding"),
+    XML_T("encoding specified in XML declaration is incorrect"),
+    XML_T("unclosed CDATA section"),
+    XML_T("error in processing external entity reference"),
+    XML_T("document is not standalone"),
+    XML_T("unexpected parser state - please send a bug report")
+  };
+  if (code > 0 && code < (int)(sizeof(message)/sizeof(message[0])))
+    return message[code];
+  return 0;
+}
+
+const XML_LChar *
+XML_ExpatVersion(void) {
+  return VERSION;
+}
+
+XML_Expat_Version
+XML_ExpatVersionInfo(void) {
+  XML_Expat_Version version;
+
+  version.major = XML_MAJOR_VERSION;
+  version.minor = XML_MINOR_VERSION;
+  version.micro = XML_MICRO_VERSION;
+
+  return version;
+}
+
+static
+enum XML_Error contentProcessor(XML_Parser parser,
+                                const char *start,
+                                const char *end,
+                                const char **endPtr)
+{
+  return doContent(parser, 0, encoding, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor(XML_Parser parser,
+                                           const char *start,
+                                           const char *end,
+                                           const char **endPtr)
+{
+  enum XML_Error result = initializeEncoding(parser);
+  if (result != XML_ERROR_NONE)
+    return result;
+  processor = externalEntityInitProcessor2;
+  return externalEntityInitProcessor2(parser, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor2(XML_Parser parser,
+                                            const char *start,
+                                            const char *end,
+                                            const char **endPtr)
+{
+  const char *next;
+  int tok = XmlContentTok(encoding, start, end, &next);
+  switch (tok) {
+  case XML_TOK_BOM:
+    start = next;
+    break;
+  case XML_TOK_PARTIAL:
+    if (endPtr) {
+      *endPtr = start;
+      return XML_ERROR_NONE;
+    }
+    eventPtr = start;
+    return XML_ERROR_UNCLOSED_TOKEN;
+  case XML_TOK_PARTIAL_CHAR:
+    if (endPtr) {
+      *endPtr = start;
+      return XML_ERROR_NONE;
+    }
+    eventPtr = start;
+    return XML_ERROR_PARTIAL_CHAR;
+  }
+  processor = externalEntityInitProcessor3;
+  return externalEntityInitProcessor3(parser, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor3(XML_Parser parser,
+                                            const char *start,
+                                            const char *end,
+                                            const char **endPtr)
+{
+  const char *next;
+  int tok = XmlContentTok(encoding, start, end, &next);
+  switch (tok) {
+  case XML_TOK_XML_DECL:
+    {
+      enum XML_Error result = processXmlDecl(parser, 1, start, next);
+      if (result != XML_ERROR_NONE)
+        return result;
+      start = next;
+    }
+    break;
+  case XML_TOK_PARTIAL:
+    if (endPtr) {
+      *endPtr = start;
+      return XML_ERROR_NONE;
+    }
+    eventPtr = start;
+    return XML_ERROR_UNCLOSED_TOKEN;
+  case XML_TOK_PARTIAL_CHAR:
+    if (endPtr) {
+      *endPtr = start;
+      return XML_ERROR_NONE;
+    }
+    eventPtr = start;
+    return XML_ERROR_PARTIAL_CHAR;
+  }
+  processor = externalEntityContentProcessor;
+  tagLevel = 1;
+  return doContent(parser, 1, encoding, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityContentProcessor(XML_Parser parser,
+                                              const char *start,
+                                              const char *end,
+                                              const char **endPtr)
+{
+  return doContent(parser, 1, encoding, start, end, endPtr);
+}
+
+static enum XML_Error
+doContent(XML_Parser parser,
+          int startTagLevel,
+          const ENCODING *enc,
+          const char *s,
+          const char *end,
+          const char **nextPtr)
+{
+  const char **eventPP;
+  const char **eventEndPP;
+  if (enc == encoding) {
+    eventPP = &eventPtr;
+    eventEndPP = &eventEndPtr;
+  }
+  else {
+    eventPP = &(openInternalEntities->internalEventPtr);
+    eventEndPP = &(openInternalEntities->internalEventEndPtr);
+  }
+  *eventPP = s;
+  for (;;) {
+    const char *next = s; /* XmlContentTok doesn't always set the last arg */
+    int tok = XmlContentTok(enc, s, end, &next);
+    *eventEndPP = next;
+    switch (tok) {
+    case XML_TOK_TRAILING_CR:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      *eventEndPP = end;
+      if (characterDataHandler) {
+        XML_Char c = 0xA;
+        characterDataHandler(handlerArg, &c, 1);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, end);
+      if (startTagLevel == 0)
+        return XML_ERROR_NO_ELEMENTS;
+      if (tagLevel != startTagLevel)
+        return XML_ERROR_ASYNC_ENTITY;
+      return XML_ERROR_NONE;
+    case XML_TOK_NONE:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      if (startTagLevel > 0) {
+        if (tagLevel != startTagLevel)
+          return XML_ERROR_ASYNC_ENTITY;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_NO_ELEMENTS;
+    case XML_TOK_INVALID:
+      *eventPP = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_UNCLOSED_TOKEN;
+    case XML_TOK_PARTIAL_CHAR:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_PARTIAL_CHAR;
+    case XML_TOK_ENTITY_REF:
+      {
+        const XML_Char *name;
+        ENTITY *entity;
+        XML_Char ch = XmlPredefinedEntityName(enc,
+                                              s + enc->minBytesPerChar,
+                                              next - enc->minBytesPerChar);
+        if (ch) {
+          if (characterDataHandler)
+            characterDataHandler(handlerArg, &ch, 1);
+          else if (defaultHandler)
+            reportDefault(parser, enc, s, next);
+          break;
+        }
+        name = poolStoreString(&dtd.pool, enc,
+                                s + enc->minBytesPerChar,
+                                next - enc->minBytesPerChar);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+        poolDiscard(&dtd.pool);
+        if (!entity) {
+          if (dtd.complete || dtd.standalone)
+            return XML_ERROR_UNDEFINED_ENTITY;
+          if (defaultHandler)
+            reportDefault(parser, enc, s, next);
+          break;
+        }
+        if (entity->open)
+          return XML_ERROR_RECURSIVE_ENTITY_REF;
+        if (entity->notation)
+          return XML_ERROR_BINARY_ENTITY_REF;
+        if (entity) {
+          if (entity->textPtr) {
+            enum XML_Error result;
+            OPEN_INTERNAL_ENTITY openEntity;
+            if (defaultHandler && !defaultExpandInternalEntities) {
+              reportDefault(parser, enc, s, next);
+              break;
+            }
+            entity->open = 1;
+            openEntity.next = openInternalEntities;
+            openInternalEntities = &openEntity;
+            openEntity.entity = entity;
+            openEntity.internalEventPtr = 0;
+            openEntity.internalEventEndPtr = 0;
+            result = doContent(parser,
+                               tagLevel,
+                               internalEncoding,
+                               (char *)entity->textPtr,
+                               (char *)(entity->textPtr + entity->textLen),
+                               0);
+            entity->open = 0;
+            openInternalEntities = openEntity.next;
+            if (result)
+              return result;
+          }
+          else if (externalEntityRefHandler) {
+            const XML_Char *context;
+            entity->open = 1;
+            context = getContext(parser);
+            entity->open = 0;
+            if (!context)
+              return XML_ERROR_NO_MEMORY;
+            if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+                                          context,
+                                          entity->base,
+                                          entity->systemId,
+                                          entity->publicId))
+              return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+            poolDiscard(&tempPool);
+          }
+          else if (defaultHandler)
+            reportDefault(parser, enc, s, next);
+        }
+        break;
+      }
+    case XML_TOK_START_TAG_WITH_ATTS:
+      if (!startElementHandler) {
+        enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
+        if (result)
+          return result;
+      }
+      /* fall through */
+    case XML_TOK_START_TAG_NO_ATTS:
+      {
+        TAG *tag;
+        if (freeTagList) {
+          tag = freeTagList;
+          freeTagList = freeTagList->parent;
+        }
+        else {
+          tag = MALLOC(sizeof(TAG));
+          if (!tag)
+            return XML_ERROR_NO_MEMORY;
+          tag->buf = MALLOC(INIT_TAG_BUF_SIZE);
+          if (!tag->buf)
+            return XML_ERROR_NO_MEMORY;
+          tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
+        }
+        tag->bindings = 0;
+        tag->parent = tagStack;
+        tagStack = tag;
+        tag->name.localPart = 0;
+        tag->rawName = s + enc->minBytesPerChar;
+        tag->rawNameLength = XmlNameLength(enc, tag->rawName);
+        if (nextPtr) {
+          /* Need to guarantee that:
+             tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */
+          if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
+            int bufSize = tag->rawNameLength * 4;
+            bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
+            tag->buf = REALLOC(tag->buf, bufSize);
+            if (!tag->buf)
+              return XML_ERROR_NO_MEMORY;
+            tag->bufEnd = tag->buf + bufSize;
+          }
+          memcpy(tag->buf, tag->rawName, tag->rawNameLength);
+          tag->rawName = tag->buf;
+        }
+        ++tagLevel;
+        if (startElementHandler) {
+          enum XML_Error result;
+          XML_Char *toPtr;
+          for (;;) {
+            const char *rawNameEnd = tag->rawName + tag->rawNameLength;
+            const char *fromPtr = tag->rawName;
+            int bufSize;
+            if (nextPtr)
+              toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)));
+            else
+              toPtr = (XML_Char *)tag->buf;
+            tag->name.str = toPtr;
+            XmlConvert(enc,
+                       &fromPtr, rawNameEnd,
+                       (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
+            if (fromPtr == rawNameEnd)
+              break;
+            bufSize = (tag->bufEnd - tag->buf) << 1;
+            tag->buf = REALLOC(tag->buf, bufSize);
+            if (!tag->buf)
+              return XML_ERROR_NO_MEMORY;
+            tag->bufEnd = tag->buf + bufSize;
+            if (nextPtr)
+              tag->rawName = tag->buf;
+          }
+          *toPtr = XML_T('\0');
+          result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
+          if (result)
+            return result;
+          startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts);
+          poolClear(&tempPool);
+        }
+        else {
+          tag->name.str = 0;
+          if (defaultHandler)
+            reportDefault(parser, enc, s, next);
+        }
+        break;
+      }
+    case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
+      if (!startElementHandler) {
+        enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
+        if (result)
+          return result;
+      }
+      /* fall through */
+    case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
+      if (startElementHandler || endElementHandler) {
+        const char *rawName = s + enc->minBytesPerChar;
+        enum XML_Error result;
+        BINDING *bindings = 0;
+        TAG_NAME name;
+        name.str = poolStoreString(&tempPool, enc, rawName,
+                                   rawName + XmlNameLength(enc, rawName));
+        if (!name.str)
+          return XML_ERROR_NO_MEMORY;
+        poolFinish(&tempPool);
+        result = storeAtts(parser, enc, s, &name, &bindings);
+        if (result)
+          return result;
+        poolFinish(&tempPool);
+        if (startElementHandler)
+          startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
+        if (endElementHandler) {
+          if (startElementHandler)
+            *eventPP = *eventEndPP;
+          endElementHandler(handlerArg, name.str);
+        }
+        poolClear(&tempPool);
+        while (bindings) {
+          BINDING *b = bindings;
+          if (endNamespaceDeclHandler)
+            endNamespaceDeclHandler(handlerArg, b->prefix->name);
+          bindings = bindings->nextTagBinding;
+          b->nextTagBinding = freeBindingList;
+          freeBindingList = b;
+          b->prefix->binding = b->prevPrefixBinding;
+        }
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      if (tagLevel == 0)
+        return epilogProcessor(parser, next, end, nextPtr);
+      break;
+    case XML_TOK_END_TAG:
+      if (tagLevel == startTagLevel)
+        return XML_ERROR_ASYNC_ENTITY;
+      else {
+        int len;
+        const char *rawName;
+        TAG *tag = tagStack;
+        tagStack = tag->parent;
+        tag->parent = freeTagList;
+        freeTagList = tag;
+        rawName = s + enc->minBytesPerChar*2;
+        len = XmlNameLength(enc, rawName);
+        if (len != tag->rawNameLength
+            || memcmp(tag->rawName, rawName, len) != 0) {
+          *eventPP = rawName;
+          return XML_ERROR_TAG_MISMATCH;
+        }
+        --tagLevel;
+        if (endElementHandler && tag->name.str) {
+          if (tag->name.localPart) {
+            XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen;
+            const XML_Char *from = tag->name.localPart;
+            while ((*to++ = *from++) != 0)
+              ;
+          }
+          endElementHandler(handlerArg, tag->name.str);
+        }
+        else if (defaultHandler)
+          reportDefault(parser, enc, s, next);
+        while (tag->bindings) {
+          BINDING *b = tag->bindings;
+          if (endNamespaceDeclHandler)
+            endNamespaceDeclHandler(handlerArg, b->prefix->name);
+          tag->bindings = tag->bindings->nextTagBinding;
+          b->nextTagBinding = freeBindingList;
+          freeBindingList = b;
+          b->prefix->binding = b->prevPrefixBinding;
+        }
+        if (tagLevel == 0)
+          return epilogProcessor(parser, next, end, nextPtr);
+      }
+      break;
+    case XML_TOK_CHAR_REF:
+      {
+        int n = XmlCharRefNumber(enc, s);
+        if (n < 0)
+          return XML_ERROR_BAD_CHAR_REF;
+        if (characterDataHandler) {
+          XML_Char buf[XML_ENCODE_MAX];
+          characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
+        }
+        else if (defaultHandler)
+          reportDefault(parser, enc, s, next);
+      }
+      break;
+    case XML_TOK_XML_DECL:
+      return XML_ERROR_MISPLACED_XML_PI;
+    case XML_TOK_DATA_NEWLINE:
+      if (characterDataHandler) {
+        XML_Char c = 0xA;
+        characterDataHandler(handlerArg, &c, 1);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    case XML_TOK_CDATA_SECT_OPEN:
+      {
+        enum XML_Error result;
+        if (startCdataSectionHandler)
+          startCdataSectionHandler(handlerArg);
+#if 0
+        /* Suppose you doing a transformation on a document that involves
+           changing only the character data.  You set up a defaultHandler
+           and a characterDataHandler.  The defaultHandler simply copies
+           characters through.  The characterDataHandler does the transformation
+           and writes the characters out escaping them as necessary.  This case
+           will fail to work if we leave out the following two lines (because &
+           and < inside CDATA sections will be incorrectly escaped).
+
+           However, now we have a start/endCdataSectionHandler, so it seems
+           easier to let the user deal with this. */
+
+        else if (characterDataHandler)
+          characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+        else if (defaultHandler)
+          reportDefault(parser, enc, s, next);
+        result = doCdataSection(parser, enc, &next, end, nextPtr);
+        if (!next) {
+          processor = cdataSectionProcessor;
+          return result;
+        }
+      }
+      break;
+    case XML_TOK_TRAILING_RSQB:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      if (characterDataHandler) {
+        if (MUST_CONVERT(enc, s)) {
+          ICHAR *dataPtr = (ICHAR *)dataBuf;
+          XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+          characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+        }
+        else
+          characterDataHandler(handlerArg,
+                               (XML_Char *)s,
+                               (XML_Char *)end - (XML_Char *)s);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, end);
+      if (startTagLevel == 0) {
+        *eventPP = end;
+        return XML_ERROR_NO_ELEMENTS;
+      }
+      if (tagLevel != startTagLevel) {
+        *eventPP = end;
+        return XML_ERROR_ASYNC_ENTITY;
+      }
+      return XML_ERROR_NONE;
+    case XML_TOK_DATA_CHARS:
+      if (characterDataHandler) {
+        if (MUST_CONVERT(enc, s)) {
+          for (;;) {
+            ICHAR *dataPtr = (ICHAR *)dataBuf;
+            XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+            *eventEndPP = s;
+            characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+            if (s == next)
+              break;
+            *eventPP = s;
+          }
+        }
+        else
+          characterDataHandler(handlerArg,
+                               (XML_Char *)s,
+                               (XML_Char *)next - (XML_Char *)s);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    case XML_TOK_PI:
+      if (!reportProcessingInstruction(parser, enc, s, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_COMMENT:
+      if (!reportComment(parser, enc, s, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    default:
+      if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    }
+    *eventPP = s = next;
+  }
+  /* not reached */
+}
+
+/* If tagNamePtr is non-null, build a real list of attributes,
+otherwise just check the attributes for well-formedness. */
+
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
+                                const char *attStr, TAG_NAME *tagNamePtr,
+                                BINDING **bindingsPtr)
+{
+  ELEMENT_TYPE *elementType = 0;
+  int nDefaultAtts = 0;
+  const XML_Char **appAtts;   /* the attribute list to pass to the application */
+  int attIndex = 0;
+  int i;
+  int n;
+  int nPrefixes = 0;
+  BINDING *binding;
+  const XML_Char *localPart;
+
+  /* lookup the element type name */
+  if (tagNamePtr) {
+    elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str,0);
+    if (!elementType) {
+      tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str);
+      if (!tagNamePtr->str)
+        return XML_ERROR_NO_MEMORY;
+      elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
+      if (!elementType)
+        return XML_ERROR_NO_MEMORY;
+      if (ns && !setElementTypePrefix(parser, elementType))
+        return XML_ERROR_NO_MEMORY;
+    }
+    nDefaultAtts = elementType->nDefaultAtts;
+  }
+  /* get the attributes from the tokenizer */
+  n = XmlGetAttributes(enc, attStr, attsSize, atts);
+  if (n + nDefaultAtts > attsSize) {
+    int oldAttsSize = attsSize;
+    attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
+    atts = REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
+    if (!atts)
+      return XML_ERROR_NO_MEMORY;
+    if (n > oldAttsSize)
+      XmlGetAttributes(enc, attStr, n, atts);
+  }
+  appAtts = (const XML_Char **)atts;
+  for (i = 0; i < n; i++) {
+    /* add the name and value to the attribute list */
+    ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
+                                         atts[i].name
+                                         + XmlNameLength(enc, atts[i].name));
+    if (!attId)
+      return XML_ERROR_NO_MEMORY;
+    /* detect duplicate attributes */
+    if ((attId->name)[-1]) {
+      if (enc == encoding)
+        eventPtr = atts[i].name;
+      return XML_ERROR_DUPLICATE_ATTRIBUTE;
+    }
+    (attId->name)[-1] = 1;
+    appAtts[attIndex++] = attId->name;
+    if (!atts[i].normalized) {
+      enum XML_Error result;
+      int isCdata = 1;
+
+      /* figure out whether declared as other than CDATA */
+      if (attId->maybeTokenized) {
+        int j;
+        for (j = 0; j < nDefaultAtts; j++) {
+          if (attId == elementType->defaultAtts[j].id) {
+            isCdata = elementType->defaultAtts[j].isCdata;
+            break;
+          }
+        }
+      }
+
+      /* normalize the attribute value */
+      result = storeAttributeValue(parser, enc, isCdata,
+                                   atts[i].valuePtr, atts[i].valueEnd,
+                                   &tempPool);
+      if (result)
+        return result;
+      if (tagNamePtr) {
+        appAtts[attIndex] = poolStart(&tempPool);
+        poolFinish(&tempPool);
+      }
+      else
+        poolDiscard(&tempPool);
+    }
+    else if (tagNamePtr) {
+      /* the value did not need normalizing */
+      appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
+      if (appAtts[attIndex] == 0)
+        return XML_ERROR_NO_MEMORY;
+      poolFinish(&tempPool);
+    }
+    /* handle prefixed attribute names */
+    if (attId->prefix && tagNamePtr) {
+      if (attId->xmlns) {
+        /* deal with namespace declarations here */
+        if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr))
+          return XML_ERROR_NO_MEMORY;
+        --attIndex;
+      }
+      else {
+        /* deal with other prefixed names later */
+        attIndex++;
+        nPrefixes++;
+        (attId->name)[-1] = 2;
+      }
+    }
+    else
+      attIndex++;
+  }
+  if (tagNamePtr) {
+    int j;
+    nSpecifiedAtts = attIndex;
+    if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
+      for (i = 0; i < attIndex; i += 2)
+        if (appAtts[i] == elementType->idAtt->name) {
+          idAttIndex = i;
+          break;
+        }
+    }
+    else
+      idAttIndex = -1;
+    /* do attribute defaulting */
+    for (j = 0; j < nDefaultAtts; j++) {
+      const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
+      if (!(da->id->name)[-1] && da->value) {
+        if (da->id->prefix) {
+          if (da->id->xmlns) {
+            if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr))
+              return XML_ERROR_NO_MEMORY;
+          }
+          else {
+            (da->id->name)[-1] = 2;
+            nPrefixes++;
+            appAtts[attIndex++] = da->id->name;
+            appAtts[attIndex++] = da->value;
+          }
+        }
+        else {
+          (da->id->name)[-1] = 1;
+          appAtts[attIndex++] = da->id->name;
+          appAtts[attIndex++] = da->value;
+        }
+      }
+    }
+    appAtts[attIndex] = 0;
+  }
+  i = 0;
+  if (nPrefixes) {
+    /* expand prefixed attribute names */
+    for (; i < attIndex; i += 2) {
+      if (appAtts[i][-1] == 2) {
+        ATTRIBUTE_ID *id;
+        ((XML_Char *)(appAtts[i]))[-1] = 0;
+        id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
+        if (id->prefix->binding) {
+          int j;
+          const BINDING *b = id->prefix->binding;
+          const XML_Char *s = appAtts[i];
+          for (j = 0; j < b->uriLen; j++) {
+            if (!poolAppendChar(&tempPool, b->uri[j]))
+              return XML_ERROR_NO_MEMORY;
+          }
+          while (*s++ != ':')
+            ;
+          do {
+            if (!poolAppendChar(&tempPool, *s))
+              return XML_ERROR_NO_MEMORY;
+          } while (*s++);
+          if (ns_triplets) {
+            tempPool.ptr[-1] = namespaceSeparator;
+            s = b->prefix->name;
+            do {
+              if (!poolAppendChar(&tempPool, *s))
+                return XML_ERROR_NO_MEMORY;
+            } while (*s++);
+          }
+
+          appAtts[i] = poolStart(&tempPool);
+          poolFinish(&tempPool);
+        }
+        if (!--nPrefixes)
+          break;
+      }
+      else
+        ((XML_Char *)(appAtts[i]))[-1] = 0;
+    }
+  }
+  /* clear the flags that say whether attributes were specified */
+  for (; i < attIndex; i += 2)
+    ((XML_Char *)(appAtts[i]))[-1] = 0;
+  if (!tagNamePtr)
+    return XML_ERROR_NONE;
+  for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
+    binding->attId->name[-1] = 0;
+  /* expand the element type name */
+  if (elementType->prefix) {
+    binding = elementType->prefix->binding;
+    if (!binding)
+      return XML_ERROR_NONE;
+    localPart = tagNamePtr->str;
+    while (*localPart++ != XML_T(':'))
+      ;
+  }
+  else if (dtd.defaultPrefix.binding) {
+    binding = dtd.defaultPrefix.binding;
+    localPart = tagNamePtr->str;
+  }
+  else
+    return XML_ERROR_NONE;
+  tagNamePtr->localPart = localPart;
+  tagNamePtr->uriLen = binding->uriLen;
+  for (i = 0; localPart[i++];)
+    ;
+  n = i + binding->uriLen;
+  if (n > binding->uriAlloc) {
+    TAG *p;
+    XML_Char *uri = MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
+    if (!uri)
+      return XML_ERROR_NO_MEMORY;
+    binding->uriAlloc = n + EXPAND_SPARE;
+    memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
+    for (p = tagStack; p; p = p->parent)
+      if (p->name.str == binding->uri)
+        p->name.str = uri;
+    FREE(binding->uri);
+    binding->uri = uri;
+  }
+  memcpy(binding->uri + binding->uriLen, localPart, i * sizeof(XML_Char));
+  tagNamePtr->str = binding->uri;
+  return XML_ERROR_NONE;
+}
+
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr)
+{
+  BINDING *b;
+  int len;
+  for (len = 0; uri[len]; len++)
+    ;
+  if (namespaceSeparator)
+    len++;
+  if (freeBindingList) {
+    b = freeBindingList;
+    if (len > b->uriAlloc) {
+      b->uri = REALLOC(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
+      if (!b->uri)
+        return 0;
+      b->uriAlloc = len + EXPAND_SPARE;
+    }
+    freeBindingList = b->nextTagBinding;
+  }
+  else {
+    b = MALLOC(sizeof(BINDING));
+    if (!b)
+      return 0;
+    b->uri = MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
+    if (!b->uri) {
+      FREE(b);
+      return 0;
+    }
+    b->uriAlloc = len + EXPAND_SPARE;
+  }
+  b->uriLen = len;
+  memcpy(b->uri, uri, len * sizeof(XML_Char));
+  if (namespaceSeparator)
+    b->uri[len - 1] = namespaceSeparator;
+  b->prefix = prefix;
+  b->attId = attId;
+  b->prevPrefixBinding = prefix->binding;
+  if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix)
+    prefix->binding = 0;
+  else
+    prefix->binding = b;
+  b->nextTagBinding = *bindingsPtr;
+  *bindingsPtr = b;
+  if (startNamespaceDeclHandler)
+    startNamespaceDeclHandler(handlerArg, prefix->name,
+                              prefix->binding ? uri : 0);
+  return 1;
+}
+
+/* The idea here is to avoid using stack for each CDATA section when
+the whole file is parsed with one call. */
+
+static
+enum XML_Error cdataSectionProcessor(XML_Parser parser,
+                                     const char *start,
+                                     const char *end,
+                                     const char **endPtr)
+{
+  enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr);
+  if (start) {
+    processor = contentProcessor;
+    return contentProcessor(parser, start, end, endPtr);
+  }
+  return result;
+}
+
+/* startPtr gets set to non-null is the section is closed, and to null if
+the section is not yet closed. */
+
+static
+enum XML_Error doCdataSection(XML_Parser parser,
+                              const ENCODING *enc,
+                              const char **startPtr,
+                              const char *end,
+                              const char **nextPtr)
+{
+  const char *s = *startPtr;
+  const char **eventPP;
+  const char **eventEndPP;
+  if (enc == encoding) {
+    eventPP = &eventPtr;
+    *eventPP = s;
+    eventEndPP = &eventEndPtr;
+  }
+  else {
+    eventPP = &(openInternalEntities->internalEventPtr);
+    eventEndPP = &(openInternalEntities->internalEventEndPtr);
+  }
+  *eventPP = s;
+  *startPtr = 0;
+  for (;;) {
+    const char *next;
+    int tok = XmlCdataSectionTok(enc, s, end, &next);
+    *eventEndPP = next;
+    switch (tok) {
+    case XML_TOK_CDATA_SECT_CLOSE:
+      if (endCdataSectionHandler)
+        endCdataSectionHandler(handlerArg);
+#if 0
+      /* see comment under XML_TOK_CDATA_SECT_OPEN */
+      else if (characterDataHandler)
+        characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      *startPtr = next;
+      return XML_ERROR_NONE;
+    case XML_TOK_DATA_NEWLINE:
+      if (characterDataHandler) {
+        XML_Char c = 0xA;
+        characterDataHandler(handlerArg, &c, 1);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    case XML_TOK_DATA_CHARS:
+      if (characterDataHandler) {
+        if (MUST_CONVERT(enc, s)) {
+          for (;;) {
+            ICHAR *dataPtr = (ICHAR *)dataBuf;
+            XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+            *eventEndPP = next;
+            characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+            if (s == next)
+              break;
+            *eventPP = s;
+          }
+        }
+        else
+          characterDataHandler(handlerArg,
+                               (XML_Char *)s,
+                               (XML_Char *)next - (XML_Char *)s);
+      }
+      else if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+    case XML_TOK_INVALID:
+      *eventPP = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL_CHAR:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_PARTIAL_CHAR;
+    case XML_TOK_PARTIAL:
+    case XML_TOK_NONE:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_UNCLOSED_CDATA_SECTION;
+    default:
+      *eventPP = next;
+      return XML_ERROR_UNEXPECTED_STATE;
+    }
+    *eventPP = s = next;
+  }
+  /* not reached */
+}
+
+#ifdef XML_DTD
+
+/* The idea here is to avoid using stack for each IGNORE section when
+the whole file is parsed with one call. */
+
+static
+enum XML_Error ignoreSectionProcessor(XML_Parser parser,
+                                      const char *start,
+                                      const char *end,
+                                      const char **endPtr)
+{
+  enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, endPtr);
+  if (start) {
+    processor = prologProcessor;
+    return prologProcessor(parser, start, end, endPtr);
+  }
+  return result;
+}
+
+/* startPtr gets set to non-null is the section is closed, and to null if
+the section is not yet closed. */
+
+static
+enum XML_Error doIgnoreSection(XML_Parser parser,
+                               const ENCODING *enc,
+                               const char **startPtr,
+                               const char *end,
+                               const char **nextPtr)
+{
+  const char *next;
+  int tok;
+  const char *s = *startPtr;
+  const char **eventPP;
+  const char **eventEndPP;
+  if (enc == encoding) {
+    eventPP = &eventPtr;
+    *eventPP = s;
+    eventEndPP = &eventEndPtr;
+  }
+  else {
+    eventPP = &(openInternalEntities->internalEventPtr);
+    eventEndPP = &(openInternalEntities->internalEventEndPtr);
+  }
+  *eventPP = s;
+  *startPtr = 0;
+  tok = XmlIgnoreSectionTok(enc, s, end, &next);
+  *eventEndPP = next;
+  switch (tok) {
+  case XML_TOK_IGNORE_SECT:
+    if (defaultHandler)
+      reportDefault(parser, enc, s, next);
+    *startPtr = next;
+    return XML_ERROR_NONE;
+  case XML_TOK_INVALID:
+    *eventPP = next;
+    return XML_ERROR_INVALID_TOKEN;
+  case XML_TOK_PARTIAL_CHAR:
+    if (nextPtr) {
+      *nextPtr = s;
+      return XML_ERROR_NONE;
+    }
+    return XML_ERROR_PARTIAL_CHAR;
+  case XML_TOK_PARTIAL:
+  case XML_TOK_NONE:
+    if (nextPtr) {
+      *nextPtr = s;
+      return XML_ERROR_NONE;
+    }
+    return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
+  default:
+    *eventPP = next;
+    return XML_ERROR_UNEXPECTED_STATE;
+  }
+  /* not reached */
+}
+
+#endif /* XML_DTD */
+
+static enum XML_Error
+initializeEncoding(XML_Parser parser)
+{
+  const char *s;
+#ifdef XML_UNICODE
+  char encodingBuf[128];
+  if (!protocolEncodingName)
+    s = 0;
+  else {
+    int i;
+    for (i = 0; protocolEncodingName[i]; i++) {
+      if (i == sizeof(encodingBuf) - 1
+          || (protocolEncodingName[i] & ~0x7f) != 0) {
+        encodingBuf[0] = '\0';
+        break;
+      }
+      encodingBuf[i] = (char)protocolEncodingName[i];
+    }
+    encodingBuf[i] = '\0';
+    s = encodingBuf;
+  }
+#else
+  s = protocolEncodingName;
+#endif
+  if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
+    return XML_ERROR_NONE;
+  return handleUnknownEncoding(parser, protocolEncodingName);
+}
+
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
+               const char *s, const char *next)
+{
+  const char *encodingName = 0;
+  const char *storedEncName = 0;
+  const ENCODING *newEncoding = 0;
+  const char *version = 0;
+  const char *versionend;
+  const char *storedversion = 0;
+  int standalone = -1;
+  if (!(ns
+        ? XmlParseXmlDeclNS
+        : XmlParseXmlDecl)(isGeneralTextEntity,
+                           encoding,
+                           s,
+                           next,
+                           &eventPtr,
+                           &version,
+                           &versionend,
+                           &encodingName,
+                           &newEncoding,
+                           &standalone))
+    return XML_ERROR_SYNTAX;
+  if (!isGeneralTextEntity && standalone == 1) {
+    dtd.standalone = 1;
+#ifdef XML_DTD
+    if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
+      paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+#endif /* XML_DTD */
+  }
+  if (xmlDeclHandler) {
+    if (encodingName) {
+      storedEncName = poolStoreString(&temp2Pool,
+                                      encoding,
+                                      encodingName,
+                                      encodingName
+                                      + XmlNameLength(encoding, encodingName));
+      if (! storedEncName)
+        return XML_ERROR_NO_MEMORY;
+      poolFinish(&temp2Pool);
+    }
+    if (version) {
+      storedversion = poolStoreString(&temp2Pool,
+                                      encoding,
+                                      version,
+                                      versionend - encoding->minBytesPerChar);
+      if (! storedversion)
+        return XML_ERROR_NO_MEMORY;
+    }
+    xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
+  }
+  else if (defaultHandler)
+    reportDefault(parser, encoding, s, next);
+  if (!protocolEncodingName) {
+    if (newEncoding) {
+      if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
+        eventPtr = encodingName;
+        return XML_ERROR_INCORRECT_ENCODING;
+      }
+      encoding = newEncoding;
+    }
+    else if (encodingName) {
+      enum XML_Error result;
+      if (! storedEncName) {
+        storedEncName = poolStoreString(&temp2Pool,
+                                        encoding,
+                                        encodingName,
+                                        encodingName
+                                        + XmlNameLength(encoding, encodingName));
+        if (! storedEncName)
+          return XML_ERROR_NO_MEMORY;
+      }
+      result = handleUnknownEncoding(parser, storedEncName);
+      poolClear(&tempPool);
+      if (result == XML_ERROR_UNKNOWN_ENCODING)
+        eventPtr = encodingName;
+      return result;
+    }
+  }
+
+  if (storedEncName || storedversion)
+    poolClear(&temp2Pool);
+
+  return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+  if (unknownEncodingHandler) {
+    XML_Encoding info;
+    int i;
+    for (i = 0; i < 256; i++)
+      info.map[i] = -1;
+    info.convert = 0;
+    info.data = 0;
+    info.release = 0;
+    if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) {
+      ENCODING *enc;
+      unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
+      if (!unknownEncodingMem) {
+        if (info.release)
+          info.release(info.data);
+        return XML_ERROR_NO_MEMORY;
+      }
+      enc = (ns
+             ? XmlInitUnknownEncodingNS
+             : XmlInitUnknownEncoding)(unknownEncodingMem,
+                                       info.map,
+                                       info.convert,
+                                       info.data);
+      if (enc) {
+        unknownEncodingData = info.data;
+        unknownEncodingRelease = info.release;
+        encoding = enc;
+        return XML_ERROR_NONE;
+      }
+    }
+    if (info.release)
+      info.release(info.data);
+  }
+  return XML_ERROR_UNKNOWN_ENCODING;
+}
+
+static enum XML_Error
+prologInitProcessor(XML_Parser parser,
+                    const char *s,
+                    const char *end,
+                    const char **nextPtr)
+{
+  enum XML_Error result = initializeEncoding(parser);
+  if (result != XML_ERROR_NONE)
+    return result;
+  processor = prologProcessor;
+  return prologProcessor(parser, s, end, nextPtr);
+}
+
+static enum XML_Error
+prologProcessor(XML_Parser parser,
+                const char *s,
+                const char *end,
+                const char **nextPtr)
+{
+  const char *next;
+  int tok = XmlPrologTok(encoding, s, end, &next);
+  return doProlog(parser, encoding, s, end, tok, next, nextPtr);
+}
+
+static enum XML_Error
+doProlog(XML_Parser parser,
+         const ENCODING *enc,
+         const char *s,
+         const char *end,
+         int tok,
+         const char *next,
+         const char **nextPtr)
+{
+#ifdef XML_DTD
+  static const XML_Char externalSubsetName[] = { '#' , '\0' };
+#endif /* XML_DTD */
+
+  const char **eventPP;
+  const char **eventEndPP;
+  enum XML_Content_Quant quant;
+
+  if (enc == encoding) {
+    eventPP = &eventPtr;
+    eventEndPP = &eventEndPtr;
+  }
+  else {
+    eventPP = &(openInternalEntities->internalEventPtr);
+    eventEndPP = &(openInternalEntities->internalEventEndPtr);
+  }
+  for (;;) {
+    int role;
+    *eventPP = s;
+    *eventEndPP = next;
+    if (tok <= 0) {
+      if (nextPtr != 0 && tok != XML_TOK_INVALID) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      switch (tok) {
+      case XML_TOK_INVALID:
+        *eventPP = next;
+        return XML_ERROR_INVALID_TOKEN;
+      case XML_TOK_PARTIAL:
+        return XML_ERROR_UNCLOSED_TOKEN;
+      case XML_TOK_PARTIAL_CHAR:
+        return XML_ERROR_PARTIAL_CHAR;
+      case XML_TOK_NONE:
+#ifdef XML_DTD
+        if (enc != encoding)
+          return XML_ERROR_NONE;
+        if (parentParser) {
+          if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
+              == XML_ROLE_ERROR)
+            return XML_ERROR_SYNTAX;
+          hadExternalDoctype = 0;
+          return XML_ERROR_NONE;
+        }
+#endif /* XML_DTD */
+        return XML_ERROR_NO_ELEMENTS;
+      default:
+        tok = -tok;
+        next = end;
+        break;
+      }
+    }
+    role = XmlTokenRole(&prologState, tok, s, next, enc);
+    switch (role) {
+    case XML_ROLE_XML_DECL:
+      {
+        enum XML_Error result = processXmlDecl(parser, 0, s, next);
+        if (result != XML_ERROR_NONE)
+          return result;
+        enc = encoding;
+      }
+      break;
+    case XML_ROLE_DOCTYPE_NAME:
+      if (startDoctypeDeclHandler) {
+        doctypeName = poolStoreString(&tempPool, enc, s, next);
+        if (! doctypeName)
+          return XML_ERROR_NO_MEMORY;
+        poolFinish(&tempPool);
+        doctypeSysid = 0;
+        doctypePubid = 0;
+      }
+      break;
+    case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
+      if (startDoctypeDeclHandler) {
+        startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
+                                doctypePubid, 1);
+        doctypeName = 0;
+        poolClear(&tempPool);
+      }
+      break;
+#ifdef XML_DTD
+    case XML_ROLE_TEXT_DECL:
+      {
+        enum XML_Error result = processXmlDecl(parser, 1, s, next);
+        if (result != XML_ERROR_NONE)
+          return result;
+        enc = encoding;
+      }
+      break;
+#endif /* XML_DTD */
+    case XML_ROLE_DOCTYPE_PUBLIC_ID:
+      if (startDoctypeDeclHandler) {
+        doctypePubid = poolStoreString(&tempPool, enc, s + 1, next - 1);
+        if (! doctypePubid)
+          return XML_ERROR_NO_MEMORY;
+        poolFinish(&tempPool);
+      }
+#ifdef XML_DTD
+      declEntity = (ENTITY *)lookup(&dtd.paramEntities,
+                                    externalSubsetName,
+                                    sizeof(ENTITY));
+      if (!declEntity)
+        return XML_ERROR_NO_MEMORY;
+#endif /* XML_DTD */
+      /* fall through */
+    case XML_ROLE_ENTITY_PUBLIC_ID:
+      if (!XmlIsPublicId(enc, s, next, eventPP))
+        return XML_ERROR_SYNTAX;
+      if (declEntity) {
+        XML_Char *tem = poolStoreString(&dtd.pool,
+                                        enc,
+                                        s + enc->minBytesPerChar,
+                                        next - enc->minBytesPerChar);
+        if (!tem)
+          return XML_ERROR_NO_MEMORY;
+        normalizePublicId(tem);
+        declEntity->publicId = tem;
+        poolFinish(&dtd.pool);
+      }
+      break;
+    case XML_ROLE_DOCTYPE_CLOSE:
+      if (doctypeName) {
+        startDoctypeDeclHandler(handlerArg, doctypeName,
+                                doctypeSysid, doctypePubid, 0);
+        poolClear(&tempPool);
+      }
+      if (dtd.complete && hadExternalDoctype) {
+        dtd.complete = 0;
+#ifdef XML_DTD
+        if (paramEntityParsing && externalEntityRefHandler) {
+          ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities,
+                                            externalSubsetName,
+                                            0);
+          if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+                                        0,
+                                        entity->base,
+                                        entity->systemId,
+                                        entity->publicId))
+           return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+        }
+#endif /* XML_DTD */
+        if (!dtd.complete
+            && !dtd.standalone
+            && notStandaloneHandler
+            && !notStandaloneHandler(handlerArg))
+          return XML_ERROR_NOT_STANDALONE;
+      }
+      if (endDoctypeDeclHandler)
+        endDoctypeDeclHandler(handlerArg);
+      break;
+    case XML_ROLE_INSTANCE_START:
+      processor = contentProcessor;
+      return contentProcessor(parser, s, end, nextPtr);
+    case XML_ROLE_ATTLIST_ELEMENT_NAME:
+      declElementType = getElementType(parser, enc, s, next);
+      if (!declElementType)
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_ROLE_ATTRIBUTE_NAME:
+      declAttributeId = getAttributeId(parser, enc, s, next);
+      if (!declAttributeId)
+        return XML_ERROR_NO_MEMORY;
+      declAttributeIsCdata = 0;
+      declAttributeType = 0;
+      declAttributeIsId = 0;
+      break;
+    case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
+      declAttributeIsCdata = 1;
+      declAttributeType = "CDATA";
+      break;
+    case XML_ROLE_ATTRIBUTE_TYPE_ID:
+      declAttributeIsId = 1;
+      declAttributeType = "ID";
+      break;
+    case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
+      declAttributeType = "IDREF";
+      break;
+    case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
+      declAttributeType = "IDREFS";
+      break;
+    case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
+      declAttributeType = "ENTITY";
+      break;
+    case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
+      declAttributeType = "ENTITIES";
+      break;
+    case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
+      declAttributeType = "NMTOKEN";
+      break;
+    case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
+      declAttributeType = "NMTOKENS";
+      break;
+
+    case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
+    case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
+      if (attlistDeclHandler)
+      {
+        char *prefix;
+        if (declAttributeType) {
+          prefix = "|";
+        }
+        else {
+          prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
+                    ? "NOTATION("
+                    : "(");
+        }
+        if (! poolAppendString(&tempPool, prefix))
+          return XML_ERROR_NO_MEMORY;
+        if (! poolAppend(&tempPool, enc, s, next))
+          return XML_ERROR_NO_MEMORY;
+        declAttributeType = tempPool.start;
+      }
+      break;
+    case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
+    case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
+      if (dtd.complete
+          && !defineAttribute(declElementType, declAttributeId,
+                              declAttributeIsCdata, declAttributeIsId, 0,
+                              parser))
+        return XML_ERROR_NO_MEMORY;
+      if (attlistDeclHandler && declAttributeType) {
+        if (*declAttributeType == '('
+            || (*declAttributeType == 'N' && declAttributeType[1] == 'O')) {
+          /* Enumerated or Notation type */
+          if (! poolAppendChar(&tempPool, ')')
+              || ! poolAppendChar(&tempPool, '\0'))
+            return XML_ERROR_NO_MEMORY;
+          declAttributeType = tempPool.start;
+          poolFinish(&tempPool);
+        }
+        *eventEndPP = s;
+        attlistDeclHandler(handlerArg, declElementType->name,
+                           declAttributeId->name, declAttributeType,
+                           0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
+        poolClear(&tempPool);
+      }
+      break;
+    case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
+    case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
+      {
+        const XML_Char *attVal;
+        enum XML_Error result
+          = storeAttributeValue(parser, enc, declAttributeIsCdata,
+                                s + enc->minBytesPerChar,
+                                next - enc->minBytesPerChar,
+                                &dtd.pool);
+        if (result)
+          return result;
+        attVal = poolStart(&dtd.pool);
+        poolFinish(&dtd.pool);
+        if (dtd.complete
+            /* ID attributes aren't allowed to have a default */
+            && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0, attVal, parser))
+          return XML_ERROR_NO_MEMORY;
+        if (attlistDeclHandler && declAttributeType) {
+          if (*declAttributeType == '('
+              || (*declAttributeType == 'N' && declAttributeType[1] == 'O')) {
+            /* Enumerated or Notation type */
+            if (! poolAppendChar(&tempPool, ')')
+                || ! poolAppendChar(&tempPool, '\0'))
+              return XML_ERROR_NO_MEMORY;
+            declAttributeType = tempPool.start;
+            poolFinish(&tempPool);
+          }
+          *eventEndPP = s;
+          attlistDeclHandler(handlerArg, declElementType->name,
+                             declAttributeId->name, declAttributeType,
+                             attVal,
+                             role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
+          poolClear(&tempPool);
+        }
+        break;
+      }
+    case XML_ROLE_ENTITY_VALUE:
+      {
+        enum XML_Error result = storeEntityValue(parser, enc,
+                                                 s + enc->minBytesPerChar,
+                                                 next - enc->minBytesPerChar);
+        if (declEntity) {
+          declEntity->textPtr = poolStart(&dtd.pool);
+          declEntity->textLen = poolLength(&dtd.pool);
+          poolFinish(&dtd.pool);
+          if (entityDeclHandler) {
+            *eventEndPP = s;
+            entityDeclHandler(handlerArg,
+                              declEntity->name,
+                              declEntity->is_param,
+                              declEntity->textPtr,
+                              declEntity->textLen,
+                              curBase, 0, 0, 0);
+          }
+        }
+        else
+          poolDiscard(&dtd.pool);
+        if (result != XML_ERROR_NONE)
+          return result;
+      }
+      break;
+    case XML_ROLE_DOCTYPE_SYSTEM_ID:
+      if (startDoctypeDeclHandler) {
+        doctypeSysid = poolStoreString(&tempPool, enc, s + 1, next - 1);
+        if (! doctypeSysid)
+          return XML_ERROR_NO_MEMORY;
+        poolFinish(&tempPool);
+      }
+      if (!dtd.standalone
+#ifdef XML_DTD
+          && !paramEntityParsing
+#endif /* XML_DTD */
+          && notStandaloneHandler
+          && !notStandaloneHandler(handlerArg))
+        return XML_ERROR_NOT_STANDALONE;
+      hadExternalDoctype = 1;
+#ifndef XML_DTD
+      break;
+#else /* XML_DTD */
+      if (!declEntity) {
+        declEntity = (ENTITY *)lookup(&dtd.paramEntities,
+                                      externalSubsetName,
+                                      sizeof(ENTITY));
+        declEntity->publicId = 0;
+        if (!declEntity)
+          return XML_ERROR_NO_MEMORY;
+      }
+      /* fall through */
+#endif /* XML_DTD */
+    case XML_ROLE_ENTITY_SYSTEM_ID:
+      if (declEntity) {
+        declEntity->systemId = poolStoreString(&dtd.pool, enc,
+                                               s + enc->minBytesPerChar,
+                                               next - enc->minBytesPerChar);
+        if (!declEntity->systemId)
+          return XML_ERROR_NO_MEMORY;
+        declEntity->base = curBase;
+        poolFinish(&dtd.pool);
+      }
+      break;
+    case XML_ROLE_ENTITY_COMPLETE:
+      if (declEntity && entityDeclHandler) {
+        *eventEndPP = s;
+        entityDeclHandler(handlerArg,
+                          declEntity->name,
+                          0,0,0,
+                          declEntity->base,
+                          declEntity->systemId,
+                          declEntity->publicId,
+                          0);
+      }
+      break;
+    case XML_ROLE_ENTITY_NOTATION_NAME:
+      if (declEntity) {
+        declEntity->notation = poolStoreString(&dtd.pool, enc, s, next);
+        if (!declEntity->notation)
+          return XML_ERROR_NO_MEMORY;
+        poolFinish(&dtd.pool);
+        if (unparsedEntityDeclHandler) {
+          *eventEndPP = s;
+          unparsedEntityDeclHandler(handlerArg,
+                                    declEntity->name,
+                                    declEntity->base,
+                                    declEntity->systemId,
+                                    declEntity->publicId,
+                                    declEntity->notation);
+        }
+        else if (entityDeclHandler) {
+          *eventEndPP = s;
+          entityDeclHandler(handlerArg,
+                            declEntity->name,
+                            0,0,0,
+                            declEntity->base,
+                            declEntity->systemId,
+                            declEntity->publicId,
+                            declEntity->notation);
+        }
+      }
+      break;
+    case XML_ROLE_GENERAL_ENTITY_NAME:
+      {
+        const XML_Char *name;
+        if (XmlPredefinedEntityName(enc, s, next)) {
+          declEntity = 0;
+          break;
+        }
+        name = poolStoreString(&dtd.pool, enc, s, next);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        if (dtd.complete) {
+          declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY));
+          if (!declEntity)
+            return XML_ERROR_NO_MEMORY;
+          if (declEntity->name != name) {
+            poolDiscard(&dtd.pool);
+            declEntity = 0;
+          }
+          else {
+            poolFinish(&dtd.pool);
+            declEntity->publicId = 0;
+            declEntity->is_param = 0;
+          }
+        }
+        else {
+          poolDiscard(&dtd.pool);
+          declEntity = 0;
+        }
+      }
+      break;
+    case XML_ROLE_PARAM_ENTITY_NAME:
+#ifdef XML_DTD
+      if (dtd.complete) {
+        const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        declEntity = (ENTITY *)lookup(&dtd.paramEntities,
+                                      name, sizeof(ENTITY));
+        if (!declEntity)
+          return XML_ERROR_NO_MEMORY;
+        if (declEntity->name != name) {
+          poolDiscard(&dtd.pool);
+          declEntity = 0;
+        }
+        else {
+          poolFinish(&dtd.pool);
+          declEntity->publicId = 0;
+          declEntity->is_param = 1;
+        }
+      }
+#else /* not XML_DTD */
+      declEntity = 0;
+#endif /* not XML_DTD */
+      break;
+    case XML_ROLE_NOTATION_NAME:
+      declNotationPublicId = 0;
+      declNotationName = 0;
+      if (notationDeclHandler) {
+        declNotationName = poolStoreString(&tempPool, enc, s, next);
+        if (!declNotationName)
+          return XML_ERROR_NO_MEMORY;
+        poolFinish(&tempPool);
+      }
+      break;
+    case XML_ROLE_NOTATION_PUBLIC_ID:
+      if (!XmlIsPublicId(enc, s, next, eventPP))
+        return XML_ERROR_SYNTAX;
+      if (declNotationName) {
+        XML_Char *tem = poolStoreString(&tempPool,
+                                        enc,
+                                        s + enc->minBytesPerChar,
+                                        next - enc->minBytesPerChar);
+        if (!tem)
+          return XML_ERROR_NO_MEMORY;
+        normalizePublicId(tem);
+        declNotationPublicId = tem;
+        poolFinish(&tempPool);
+      }
+      break;
+    case XML_ROLE_NOTATION_SYSTEM_ID:
+      if (declNotationName && notationDeclHandler) {
+        const XML_Char *systemId
+          = poolStoreString(&tempPool, enc,
+                            s + enc->minBytesPerChar,
+                            next - enc->minBytesPerChar);
+        if (!systemId)
+          return XML_ERROR_NO_MEMORY;
+        *eventEndPP = s;
+        notationDeclHandler(handlerArg,
+                            declNotationName,
+                            curBase,
+                            systemId,
+                            declNotationPublicId);
+      }
+      poolClear(&tempPool);
+      break;
+    case XML_ROLE_NOTATION_NO_SYSTEM_ID:
+      if (declNotationPublicId && notationDeclHandler) {
+        *eventEndPP = s;
+        notationDeclHandler(handlerArg,
+                            declNotationName,
+                            curBase,
+                            0,
+                            declNotationPublicId);
+      }
+      poolClear(&tempPool);
+      break;
+    case XML_ROLE_ERROR:
+      switch (tok) {
+      case XML_TOK_PARAM_ENTITY_REF:
+        return XML_ERROR_PARAM_ENTITY_REF;
+      case XML_TOK_XML_DECL:
+        return XML_ERROR_MISPLACED_XML_PI;
+      default:
+        return XML_ERROR_SYNTAX;
+      }
+#ifdef XML_DTD
+    case XML_ROLE_IGNORE_SECT:
+      {
+        enum XML_Error result;
+        if (defaultHandler)
+          reportDefault(parser, enc, s, next);
+        result = doIgnoreSection(parser, enc, &next, end, nextPtr);
+        if (!next) {
+          processor = ignoreSectionProcessor;
+          return result;
+        }
+      }
+      break;
+#endif /* XML_DTD */
+    case XML_ROLE_GROUP_OPEN:
+      if (prologState.level >= groupSize) {
+        if (groupSize) {
+          groupConnector = REALLOC(groupConnector, groupSize *= 2);
+          if (dtd.scaffIndex)
+            dtd.scaffIndex = REALLOC(dtd.scaffIndex, groupSize * sizeof(int));
+        }
+        else
+          groupConnector = MALLOC(groupSize = 32);
+        if (!groupConnector)
+          return XML_ERROR_NO_MEMORY;
+      }
+      groupConnector[prologState.level] = 0;
+      if (dtd.in_eldecl) {
+        int myindex = nextScaffoldPart(parser);
+        if (myindex < 0)
+          return XML_ERROR_NO_MEMORY;
+        dtd.scaffIndex[dtd.scaffLevel] = myindex;
+        dtd.scaffLevel++;
+        dtd.scaffold[myindex].type = XML_CTYPE_SEQ;
+      }
+      break;
+    case XML_ROLE_GROUP_SEQUENCE:
+      if (groupConnector[prologState.level] == '|')
+        return XML_ERROR_SYNTAX;
+      groupConnector[prologState.level] = ',';
+      break;
+    case XML_ROLE_GROUP_CHOICE:
+      if (groupConnector[prologState.level] == ',')
+        return XML_ERROR_SYNTAX;
+      if (dtd.in_eldecl
+          && ! groupConnector[prologState.level]
+          && dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]].type != XML_CTYPE_MIXED
+          ) {
+        dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]].type = XML_CTYPE_CHOICE;
+      }
+      groupConnector[prologState.level] = '|';
+      break;
+    case XML_ROLE_PARAM_ENTITY_REF:
+#ifdef XML_DTD
+    case XML_ROLE_INNER_PARAM_ENTITY_REF:
+      if (paramEntityParsing
+          && (dtd.complete || role == XML_ROLE_INNER_PARAM_ENTITY_REF)) {
+        const XML_Char *name;
+        ENTITY *entity;
+        name = poolStoreString(&dtd.pool, enc,
+                                s + enc->minBytesPerChar,
+                                next - enc->minBytesPerChar);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
+        poolDiscard(&dtd.pool);
+        if (!entity) {
+          /* FIXME what to do if !dtd.complete? */
+          return XML_ERROR_UNDEFINED_ENTITY;
+        }
+        if (entity->open)
+          return XML_ERROR_RECURSIVE_ENTITY_REF;
+        if (entity->textPtr) {
+          enum XML_Error result;
+          result = processInternalParamEntity(parser, entity);
+          if (result != XML_ERROR_NONE)
+            return result;
+          break;
+        }
+        if (role == XML_ROLE_INNER_PARAM_ENTITY_REF)
+          return XML_ERROR_PARAM_ENTITY_REF;
+        if (externalEntityRefHandler) {
+          dtd.complete = 0;
+          entity->open = 1;
+          if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+                                        0,
+                                        entity->base,
+                                        entity->systemId,
+                                        entity->publicId)) {
+            entity->open = 0;
+            return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+          }
+          entity->open = 0;
+          if (dtd.complete)
+            break;
+        }
+      }
+#endif /* XML_DTD */
+      if (!dtd.standalone
+          && notStandaloneHandler
+          && !notStandaloneHandler(handlerArg))
+        return XML_ERROR_NOT_STANDALONE;
+      dtd.complete = 0;
+      if (defaultHandler)
+        reportDefault(parser, enc, s, next);
+      break;
+
+      /* Element declaration stuff */
+
+    case XML_ROLE_ELEMENT_NAME:
+      if (elementDeclHandler) {
+        declElementType = getElementType(parser, enc, s, next);
+        if (! declElementType)
+          return XML_ERROR_NO_MEMORY;
+        dtd.scaffLevel = 0;
+        dtd.scaffCount = 0;
+        dtd.in_eldecl = 1;
+      }
+      break;
+
+    case XML_ROLE_CONTENT_ANY:
+    case XML_ROLE_CONTENT_EMPTY:
+      if (dtd.in_eldecl) {
+        if (elementDeclHandler) {
+          XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
+          if (! content)
+            return XML_ERROR_NO_MEMORY;
+          content->quant = XML_CQUANT_NONE;
+          content->name = 0;
+          content->numchildren = 0;
+          content->children = 0;
+          content->type = ((role == XML_ROLE_CONTENT_ANY) ?
+                           XML_CTYPE_ANY :
+                           XML_CTYPE_EMPTY);
+          *eventEndPP = s;
+          elementDeclHandler(handlerArg, declElementType->name, content);
+        }
+        dtd.in_eldecl = 0;
+      }
+      break;
+      
+    case XML_ROLE_CONTENT_PCDATA:
+      if (dtd.in_eldecl) {
+        dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]].type = XML_CTYPE_MIXED;
+      }
+      break;
+
+    case XML_ROLE_CONTENT_ELEMENT:
+      quant = XML_CQUANT_NONE;
+      goto elementContent;
+    case XML_ROLE_CONTENT_ELEMENT_OPT:
+      quant = XML_CQUANT_OPT;
+      goto elementContent;
+    case XML_ROLE_CONTENT_ELEMENT_REP:
+      quant = XML_CQUANT_REP;
+      goto elementContent;
+    case XML_ROLE_CONTENT_ELEMENT_PLUS:
+      quant = XML_CQUANT_PLUS;
+    elementContent:
+      if (dtd.in_eldecl)
+        {
+          ELEMENT_TYPE *el;
+          const char *nxt = quant == XML_CQUANT_NONE ? next : next - 1;
+          int myindex = nextScaffoldPart(parser);
+          if (myindex < 0)
+            return XML_ERROR_NO_MEMORY;
+          dtd.scaffold[myindex].type = XML_CTYPE_NAME;
+          dtd.scaffold[myindex].quant = quant;
+          el = getElementType(parser, enc, s, nxt);
+          if (! el)
+            return XML_ERROR_NO_MEMORY;
+          dtd.scaffold[myindex].name = el->name;
+          dtd.contentStringLen +=  nxt - s + 1;
+        }
+      break;
+
+    case XML_ROLE_GROUP_CLOSE:
+      quant = XML_CQUANT_NONE;
+      goto closeGroup;
+    case XML_ROLE_GROUP_CLOSE_OPT:
+      quant = XML_CQUANT_OPT;
+      goto closeGroup;
+    case XML_ROLE_GROUP_CLOSE_REP:
+      quant = XML_CQUANT_REP;
+      goto closeGroup;
+    case XML_ROLE_GROUP_CLOSE_PLUS:
+      quant = XML_CQUANT_PLUS;
+    closeGroup:
+      if (dtd.in_eldecl) {
+        dtd.scaffLevel--;
+        dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel]].quant = quant;
+        if (dtd.scaffLevel == 0) {
+          if (elementDeclHandler) {
+            XML_Content *model = build_model(parser);
+            if (! model)
+              return XML_ERROR_NO_MEMORY;
+            *eventEndPP = s;
+            elementDeclHandler(handlerArg, declElementType->name, model);
+          }
+          dtd.in_eldecl = 0;
+          dtd.contentStringLen = 0;
+        }
+      }
+      break;
+      /* End element declaration stuff */
+
+    case XML_ROLE_NONE:
+      switch (tok) {
+      case XML_TOK_PI:
+        if (!reportProcessingInstruction(parser, enc, s, next))
+          return XML_ERROR_NO_MEMORY;
+        break;
+      case XML_TOK_COMMENT:
+        if (!reportComment(parser, enc, s, next))
+          return XML_ERROR_NO_MEMORY;
+        break;
+      }
+      break;
+    }
+    if (defaultHandler) {
+      switch (tok) {
+      case XML_TOK_PI:
+      case XML_TOK_COMMENT:
+      case XML_TOK_BOM:
+      case XML_TOK_XML_DECL:
+#ifdef XML_DTD
+      case XML_TOK_IGNORE_SECT:
+#endif /* XML_DTD */
+      case XML_TOK_PARAM_ENTITY_REF:
+        break;
+      default:
+#ifdef XML_DTD
+        if (role != XML_ROLE_IGNORE_SECT)
+#endif /* XML_DTD */
+          reportDefault(parser, enc, s, next);
+      }
+    }
+    s = next;
+    tok = XmlPrologTok(enc, s, end, &next);
+  }
+  /* not reached */
+}
+
+static
+enum XML_Error epilogProcessor(XML_Parser parser,
+                               const char *s,
+                               const char *end,
+                               const char **nextPtr)
+{
+  processor = epilogProcessor;
+  eventPtr = s;
+  for (;;) {
+    const char *next;
+    int tok = XmlPrologTok(encoding, s, end, &next);
+    eventEndPtr = next;
+    switch (tok) {
+    case -XML_TOK_PROLOG_S:
+      if (defaultHandler) {
+        eventEndPtr = end;
+        reportDefault(parser, encoding, s, end);
+      }
+      /* fall through */
+    case XML_TOK_NONE:
+      if (nextPtr)
+        *nextPtr = end;
+      return XML_ERROR_NONE;
+    case XML_TOK_PROLOG_S:
+      if (defaultHandler)
+        reportDefault(parser, encoding, s, next);
+      break;
+    case XML_TOK_PI:
+      if (!reportProcessingInstruction(parser, encoding, s, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_COMMENT:
+      if (!reportComment(parser, encoding, s, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_INVALID:
+      eventPtr = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_UNCLOSED_TOKEN;
+    case XML_TOK_PARTIAL_CHAR:
+      if (nextPtr) {
+        *nextPtr = s;
+        return XML_ERROR_NONE;
+      }
+      return XML_ERROR_PARTIAL_CHAR;
+    default:
+      return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+    }
+    eventPtr = s = next;
+  }
+}
+
+#ifdef XML_DTD
+
+static enum XML_Error
+processInternalParamEntity(XML_Parser parser, ENTITY *entity)
+{
+  const char *s, *end, *next;
+  int tok;
+  enum XML_Error result;
+  OPEN_INTERNAL_ENTITY openEntity;
+  entity->open = 1;
+  openEntity.next = openInternalEntities;
+  openInternalEntities = &openEntity;
+  openEntity.entity = entity;
+  openEntity.internalEventPtr = 0;
+  openEntity.internalEventEndPtr = 0;
+  s = (char *)entity->textPtr;
+  end = (char *)(entity->textPtr + entity->textLen);
+  tok = XmlPrologTok(internalEncoding, s, end, &next);
+  result = doProlog(parser, internalEncoding, s, end, tok, next, 0);
+  entity->open = 0;
+  openInternalEntities = openEntity.next;
+  return result;
+}
+
+#endif /* XML_DTD */
+
+static
+enum XML_Error errorProcessor(XML_Parser parser,
+                              const char *s,
+                              const char *end,
+                              const char **nextPtr)
+{
+  itkExpatUnused(s);
+  itkExpatUnused(end);
+  itkExpatUnused(nextPtr);
+  return errorCode;
+}
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+                    const char *ptr, const char *end,
+                    STRING_POOL *pool)
+{
+  enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
+  if (result)
+    return result;
+  if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
+    poolChop(pool);
+  if (!poolAppendChar(pool, XML_T('\0')))
+    return XML_ERROR_NO_MEMORY;
+  return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+                     const char *ptr, const char *end,
+                     STRING_POOL *pool)
+{
+  for (;;) {
+    const char *next;
+    int tok = XmlAttributeValueTok(enc, ptr, end, &next);
+    switch (tok) {
+    case XML_TOK_NONE:
+      return XML_ERROR_NONE;
+    case XML_TOK_INVALID:
+      if (enc == encoding)
+        eventPtr = next;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_PARTIAL:
+      if (enc == encoding)
+        eventPtr = ptr;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_CHAR_REF:
+      {
+        XML_Char buf[XML_ENCODE_MAX];
+        int i;
+        int n = XmlCharRefNumber(enc, ptr);
+        if (n < 0) {
+          if (enc == encoding)
+            eventPtr = ptr;
+          return XML_ERROR_BAD_CHAR_REF;
+        }
+        if (!isCdata
+            && n == 0x20 /* space */
+            && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+          break;
+        n = XmlEncode(n, (ICHAR *)buf);
+        if (!n) {
+          if (enc == encoding)
+            eventPtr = ptr;
+          return XML_ERROR_BAD_CHAR_REF;
+        }
+        for (i = 0; i < n; i++) {
+          if (!poolAppendChar(pool, buf[i]))
+            return XML_ERROR_NO_MEMORY;
+        }
+      }
+      break;
+    case XML_TOK_DATA_CHARS:
+      if (!poolAppend(pool, enc, ptr, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_TRAILING_CR:
+      next = ptr + enc->minBytesPerChar;
+      /* fall through */
+    case XML_TOK_ATTRIBUTE_VALUE_S:
+    case XML_TOK_DATA_NEWLINE:
+      if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+        break;
+      if (!poolAppendChar(pool, 0x20))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_ENTITY_REF:
+      {
+        const XML_Char *name;
+        ENTITY *entity;
+        XML_Char ch = XmlPredefinedEntityName(enc,
+                                              ptr + enc->minBytesPerChar,
+                                              next - enc->minBytesPerChar);
+        if (ch) {
+          if (!poolAppendChar(pool, ch))
+            return XML_ERROR_NO_MEMORY;
+          break;
+        }
+        name = poolStoreString(&temp2Pool, enc,
+                               ptr + enc->minBytesPerChar,
+                               next - enc->minBytesPerChar);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+        poolDiscard(&temp2Pool);
+        if (!entity) {
+          if (dtd.complete) {
+            if (enc == encoding)
+              eventPtr = ptr;
+            return XML_ERROR_UNDEFINED_ENTITY;
+          }
+        }
+        else if (entity->open) {
+          if (enc == encoding)
+            eventPtr = ptr;
+          return XML_ERROR_RECURSIVE_ENTITY_REF;
+        }
+        else if (entity->notation) {
+          if (enc == encoding)
+            eventPtr = ptr;
+          return XML_ERROR_BINARY_ENTITY_REF;
+        }
+        else if (!entity->textPtr) {
+          if (enc == encoding)
+            eventPtr = ptr;
+          return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+        }
+        else {
+          enum XML_Error result;
+          const XML_Char *textEnd = entity->textPtr + entity->textLen;
+          entity->open = 1;
+          result = appendAttributeValue(parser, internalEncoding, isCdata, (char *)entity->textPtr, (char *)textEnd, pool);
+          entity->open = 0;
+          if (result)
+            return result;
+        }
+      }
+      break;
+    default:
+      if (enc == encoding)
+        eventPtr = ptr;
+      return XML_ERROR_UNEXPECTED_STATE;
+    }
+    ptr = next;
+  }
+  /* not reached */
+}
+
+static
+enum XML_Error storeEntityValue(XML_Parser parser,
+                                const ENCODING *enc,
+                                const char *entityTextPtr,
+                                const char *entityTextEnd)
+{
+  STRING_POOL *pool = &(dtd.pool);
+  for (;;) {
+    const char *next;
+    int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
+    switch (tok) {
+    case XML_TOK_PARAM_ENTITY_REF:
+#ifdef XML_DTD
+      if (parentParser || enc != encoding) {
+        enum XML_Error result;
+        const XML_Char *name;
+        ENTITY *entity;
+        name = poolStoreString(&tempPool, enc,
+                               entityTextPtr + enc->minBytesPerChar,
+                               next - enc->minBytesPerChar);
+        if (!name)
+          return XML_ERROR_NO_MEMORY;
+        entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
+        poolDiscard(&tempPool);
+        if (!entity) {
+          if (enc == encoding)
+            eventPtr = entityTextPtr;
+          return XML_ERROR_UNDEFINED_ENTITY;
+        }
+        if (entity->open) {
+          if (enc == encoding)
+            eventPtr = entityTextPtr;
+          return XML_ERROR_RECURSIVE_ENTITY_REF;
+        }
+        if (entity->systemId) {
+          if (enc == encoding)
+            eventPtr = entityTextPtr;
+          return XML_ERROR_PARAM_ENTITY_REF;
+        }
+        entity->open = 1;
+        result = storeEntityValue(parser,
+                                  internalEncoding,
+                                  (char *)entity->textPtr,
+                                  (char *)(entity->textPtr + entity->textLen));
+        entity->open = 0;
+        if (result)
+          return result;
+        break;
+      }
+#endif /* XML_DTD */
+      eventPtr = entityTextPtr;
+      return XML_ERROR_SYNTAX;
+    case XML_TOK_NONE:
+      return XML_ERROR_NONE;
+    case XML_TOK_ENTITY_REF:
+    case XML_TOK_DATA_CHARS:
+      if (!poolAppend(pool, enc, entityTextPtr, next))
+        return XML_ERROR_NO_MEMORY;
+      break;
+    case XML_TOK_TRAILING_CR:
+      next = entityTextPtr + enc->minBytesPerChar;
+      /* fall through */
+    case XML_TOK_DATA_NEWLINE:
+      if (pool->end == pool->ptr && !poolGrow(pool))
+        return XML_ERROR_NO_MEMORY;
+      *(pool->ptr)++ = 0xA;
+      break;
+    case XML_TOK_CHAR_REF:
+      {
+        XML_Char buf[XML_ENCODE_MAX];
+        int i;
+        int n = XmlCharRefNumber(enc, entityTextPtr);
+        if (n < 0) {
+          if (enc == encoding)
+            eventPtr = entityTextPtr;
+          return XML_ERROR_BAD_CHAR_REF;
+        }
+        n = XmlEncode(n, (ICHAR *)buf);
+        if (!n) {
+          if (enc == encoding)
+            eventPtr = entityTextPtr;
+          return XML_ERROR_BAD_CHAR_REF;
+        }
+        for (i = 0; i < n; i++) {
+          if (pool->end == pool->ptr && !poolGrow(pool))
+            return XML_ERROR_NO_MEMORY;
+          *(pool->ptr)++ = buf[i];
+        }
+      }
+      break;
+    case XML_TOK_PARTIAL:
+      if (enc == encoding)
+        eventPtr = entityTextPtr;
+      return XML_ERROR_INVALID_TOKEN;
+    case XML_TOK_INVALID:
+      if (enc == encoding)
+        eventPtr = next;
+      return XML_ERROR_INVALID_TOKEN;
+    default:
+      if (enc == encoding)
+        eventPtr = entityTextPtr;
+      return XML_ERROR_UNEXPECTED_STATE;
+    }
+    entityTextPtr = next;
+  }
+  /* not reached */
+}
+
+static void
+normalizeLines(XML_Char *s)
+{
+  XML_Char *p;
+  for (;; s++) {
+    if (*s == XML_T('\0'))
+      return;
+    if (*s == 0xD)
+      break;
+  }
+  p = s;
+  do {
+    if (*s == 0xD) {
+      *p++ = 0xA;
+      if (*++s == 0xA)
+        s++;
+    }
+    else
+      *p++ = *s++;
+  } while (*s);
+  *p = XML_T('\0');
+}
+
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+  const XML_Char *target;
+  XML_Char *data;
+  const char *tem;
+  if (!processingInstructionHandler) {
+    if (defaultHandler)
+      reportDefault(parser, enc, start, end);
+    return 1;
+  }
+  start += enc->minBytesPerChar * 2;
+  tem = start + XmlNameLength(enc, start);
+  target = poolStoreString(&tempPool, enc, start, tem);
+  if (!target)
+    return 0;
+  poolFinish(&tempPool);
+  data = poolStoreString(&tempPool, enc,
+                        XmlSkipS(enc, tem),
+                        end - enc->minBytesPerChar*2);
+  if (!data)
+    return 0;
+  normalizeLines(data);
+  processingInstructionHandler(handlerArg, target, data);
+  poolClear(&tempPool);
+  return 1;
+}
+
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+  XML_Char *data;
+  if (!commentHandler) {
+    if (defaultHandler)
+      reportDefault(parser, enc, start, end);
+    return 1;
+  }
+  data = poolStoreString(&tempPool,
+                         enc,
+                         start + enc->minBytesPerChar * 4, 
+                         end - enc->minBytesPerChar * 3);
+  if (!data)
+    return 0;
+  normalizeLines(data);
+  commentHandler(handlerArg, data);
+  poolClear(&tempPool);
+  return 1;
+}
+
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end)
+{
+  if (MUST_CONVERT(enc, s)) {
+    const char **eventPP;
+    const char **eventEndPP;
+    if (enc == encoding) {
+      eventPP = &eventPtr;
+      eventEndPP = &eventEndPtr;
+    }
+    else {
+      eventPP = &(openInternalEntities->internalEventPtr);
+      eventEndPP = &(openInternalEntities->internalEventEndPtr);
+    }
+    do {
+      ICHAR *dataPtr = (ICHAR *)dataBuf;
+      XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+      *eventEndPP = s;
+      defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+      *eventPP = s;
+    } while (s != end);
+  }
+  else
+    defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
+}
+
+
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata,
+                int isId, const XML_Char *value, XML_Parser parser)
+{
+  DEFAULT_ATTRIBUTE *att;
+  if (value || isId) {
+    /* The handling of default attributes gets messed up if we have
+       a default which duplicates a non-default. */
+    int i;
+    for (i = 0; i < type->nDefaultAtts; i++)
+      if (attId == type->defaultAtts[i].id)
+        return 1;
+    if (isId && !type->idAtt && !attId->xmlns)
+      type->idAtt = attId;
+  }
+  if (type->nDefaultAtts == type->allocDefaultAtts) {
+    if (type->allocDefaultAtts == 0) {
+      type->allocDefaultAtts = 8;
+      type->defaultAtts = MALLOC(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+    }
+    else {
+      type->allocDefaultAtts *= 2;
+      type->defaultAtts = REALLOC(type->defaultAtts,
+                                  type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+    }
+    if (!type->defaultAtts)
+      return 0;
+  }
+  att = type->defaultAtts + type->nDefaultAtts;
+  att->id = attId;
+  att->value = value;
+  att->isCdata = isCdata;
+  if (!isCdata)
+    attId->maybeTokenized = 1;
+  type->nDefaultAtts += 1;
+  return 1;
+}
+
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
+{
+  const XML_Char *name;
+  for (name = elementType->name; *name; name++) {
+    if (*name == XML_T(':')) {
+      PREFIX *prefix;
+      const XML_Char *s;
+      for (s = elementType->name; s != name; s++) {
+        if (!poolAppendChar(&dtd.pool, *s))
+          return 0;
+      }
+      if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+        return 0;
+      prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+      if (!prefix)
+        return 0;
+      if (prefix->name == poolStart(&dtd.pool))
+        poolFinish(&dtd.pool);
+      else
+        poolDiscard(&dtd.pool);
+      elementType->prefix = prefix;
+
+    }
+  }
+  return 1;
+}
+
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+  ATTRIBUTE_ID *id;
+  const XML_Char *name;
+  if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+    return 0;
+  name = poolStoreString(&dtd.pool, enc, start, end);
+  if (!name)
+    return 0;
+  ++name;
+  id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
+  if (!id)
+    return 0;
+  if (id->name != name)
+    poolDiscard(&dtd.pool);
+  else {
+    poolFinish(&dtd.pool);
+    if (!ns)
+      ;
+    else if (name[0] == 'x'
+        && name[1] == 'm'
+        && name[2] == 'l'
+        && name[3] == 'n'
+        && name[4] == 's'
+        && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
+      if (name[5] == '\0')
+        id->prefix = &dtd.defaultPrefix;
+      else
+        id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
+      id->xmlns = 1;
+    }
+    else {
+      int i;
+      for (i = 0; name[i]; i++) {
+        if (name[i] == XML_T(':')) {
+          int j;
+          for (j = 0; j < i; j++) {
+            if (!poolAppendChar(&dtd.pool, name[j]))
+              return 0;
+          }
+          if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+            return 0;
+          id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+          if (id->prefix->name == poolStart(&dtd.pool))
+            poolFinish(&dtd.pool);
+          else
+            poolDiscard(&dtd.pool);
+          break;
+        }
+      }
+    }
+  }
+  return id;
+}
+
+#define CONTEXT_SEP XML_T('\f')
+
+static
+const XML_Char *getContext(XML_Parser parser)
+{
+  HASH_TABLE_ITER iter;
+  int needSep = 0;
+
+  if (dtd.defaultPrefix.binding) {
+    int i;
+    int len;
+    if (!poolAppendChar(&tempPool, XML_T('=')))
+      return 0;
+    len = dtd.defaultPrefix.binding->uriLen;
+    if (namespaceSeparator != XML_T('\0'))
+      len--;
+    for (i = 0; i < len; i++)
+      if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
+        return 0;
+    needSep = 1;
+  }
+
+  hashTableIterInit(&iter, &(dtd.prefixes));
+  for (;;) {
+    int i;
+    int len;
+    const XML_Char *s;
+    PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
+    if (!prefix)
+      break;
+    if (!prefix->binding)
+      continue;
+    if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+      return 0;
+    for (s = prefix->name; *s; s++)
+      if (!poolAppendChar(&tempPool, *s))
+        return 0;
+    if (!poolAppendChar(&tempPool, XML_T('=')))
+      return 0;
+    len = prefix->binding->uriLen;
+    if (namespaceSeparator != XML_T('\0'))
+      len--;
+    for (i = 0; i < len; i++)
+      if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
+        return 0;
+    needSep = 1;
+  }
+
+
+  hashTableIterInit(&iter, &(dtd.generalEntities));
+  for (;;) {
+    const XML_Char *s;
+    ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
+    if (!e)
+      break;
+    if (!e->open)
+      continue;
+    if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+      return 0;
+    for (s = e->name; *s; s++)
+      if (!poolAppendChar(&tempPool, *s))
+        return 0;
+    needSep = 1;
+  }
+
+  if (!poolAppendChar(&tempPool, XML_T('\0')))
+    return 0;
+  return tempPool.start;
+}
+
+static
+int setContext(XML_Parser parser, const XML_Char *context)
+{
+  const XML_Char *s = context;
+
+  while (*context != XML_T('\0')) {
+    if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
+      ENTITY *e;
+      if (!poolAppendChar(&tempPool, XML_T('\0')))
+        return 0;
+      e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0);
+      if (e)
+        e->open = 1;
+      if (*s != XML_T('\0'))
+        s++;
+      context = s;
+      poolDiscard(&tempPool);
+    }
+    else if (*s == '=') {
+      PREFIX *prefix;
+      if (poolLength(&tempPool) == 0)
+        prefix = &dtd.defaultPrefix;
+      else {
+        if (!poolAppendChar(&tempPool, XML_T('\0')))
+          return 0;
+        prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
+        if (!prefix)
+          return 0;
+        if (prefix->name == poolStart(&tempPool)) {
+          prefix->name = poolCopyString(&dtd.pool, prefix->name);
+          if (!prefix->name)
+            return 0;
+        }
+        poolDiscard(&tempPool);
+      }
+      for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++)
+        if (!poolAppendChar(&tempPool, *context))
+          return 0;
+      if (!poolAppendChar(&tempPool, XML_T('\0')))
+        return 0;
+      if (!addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings))
+        return 0;
+      poolDiscard(&tempPool);
+      if (*context != XML_T('\0'))
+        ++context;
+      s = context;
+    }
+    else {
+      if (!poolAppendChar(&tempPool, *s))
+        return 0;
+      s++;
+    }
+  }
+  return 1;
+}
+
+
+static
+void normalizePublicId(XML_Char *publicId)
+{
+  XML_Char *p = publicId;
+  XML_Char *s;
+  for (s = publicId; *s; s++) {
+    switch (*s) {
+    case 0x20:
+    case 0xD:
+    case 0xA:
+      if (p != publicId && p[-1] != 0x20)
+        *p++ = 0x20;
+      break;
+    default:
+      *p++ = *s;
+    }
+  }
+  if (p != publicId && p[-1] == 0x20)
+    --p;
+  *p = XML_T('\0');
+}
+
+static int dtdInit(DTD *p, XML_Parser parser)
+{
+  XML_Memory_Handling_Suite *ms = &((Parser *) parser)->m_mem; 
+  poolInit(&(p->pool), ms);
+  hashTableInit(&(p->generalEntities), ms);
+  hashTableInit(&(p->elementTypes), ms);
+  hashTableInit(&(p->attributeIds), ms);
+  hashTableInit(&(p->prefixes), ms);
+  p->complete = 1;
+  p->standalone = 0;
+#ifdef XML_DTD
+  hashTableInit(&(p->paramEntities), ms);
+#endif /* XML_DTD */
+  p->defaultPrefix.name = 0;
+  p->defaultPrefix.binding = 0;
+
+  p->in_eldecl = 0;
+  p->scaffIndex = 0;
+  p->scaffLevel = 0;
+  p->scaffold = 0;
+  p->contentStringLen = 0;
+  p->scaffSize = 0;
+  p->scaffCount = 0;
+
+  return 1;
+}
+
+#ifdef XML_DTD
+
+static void dtdSwap(DTD *p1, DTD *p2)
+{
+  DTD tem;
+  memcpy(&tem, p1, sizeof(DTD));
+  memcpy(p1, p2, sizeof(DTD));
+  memcpy(p2, &tem, sizeof(DTD));
+}
+
+#endif /* XML_DTD */
+
+static void dtdDestroy(DTD *p, XML_Parser parser)
+{
+  HASH_TABLE_ITER iter;
+  hashTableIterInit(&iter, &(p->elementTypes));
+  for (;;) {
+    ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+    if (!e)
+      break;
+    if (e->allocDefaultAtts != 0)
+      FREE(e->defaultAtts);
+  }
+  hashTableDestroy(&(p->generalEntities));
+#ifdef XML_DTD
+  hashTableDestroy(&(p->paramEntities));
+#endif /* XML_DTD */
+  hashTableDestroy(&(p->elementTypes));
+  hashTableDestroy(&(p->attributeIds));
+  hashTableDestroy(&(p->prefixes));
+  poolDestroy(&(p->pool));
+  if (p->scaffIndex)
+    FREE(p->scaffIndex);
+  if (p->scaffold)
+    FREE(p->scaffold);
+}
+
+/* Do a deep copy of the DTD.  Return 0 for out of memory; non-zero otherwise.
+The new DTD has already been initialized. */
+
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd, XML_Parser parser)
+{
+  HASH_TABLE_ITER iter;
+
+  /* Copy the prefix table. */
+
+  hashTableIterInit(&iter, &(oldDtd->prefixes));
+  for (;;) {
+    const XML_Char *name;
+    const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
+    if (!oldP)
+      break;
+    name = poolCopyString(&(newDtd->pool), oldP->name);
+    if (!name)
+      return 0;
+    if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
+      return 0;
+  }
+
+  hashTableIterInit(&iter, &(oldDtd->attributeIds));
+
+  /* Copy the attribute id table. */
+
+  for (;;) {
+    ATTRIBUTE_ID *newA;
+    const XML_Char *name;
+    const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
+
+    if (!oldA)
+      break;
+    /* Remember to allocate the scratch byte before the name. */
+    if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
+      return 0;
+    name = poolCopyString(&(newDtd->pool), oldA->name);
+    if (!name)
+      return 0;
+    ++name;
+    newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
+    if (!newA)
+      return 0;
+    newA->maybeTokenized = oldA->maybeTokenized;
+    if (oldA->prefix) {
+      newA->xmlns = oldA->xmlns;
+      if (oldA->prefix == &oldDtd->defaultPrefix)
+        newA->prefix = &newDtd->defaultPrefix;
+      else
+        newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldA->prefix->name, 0);
+    }
+  }
+
+  /* Copy the element type table. */
+
+  hashTableIterInit(&iter, &(oldDtd->elementTypes));
+
+  for (;;) {
+    int i;
+    ELEMENT_TYPE *newE;
+    const XML_Char *name;
+    const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+    if (!oldE)
+      break;
+    name = poolCopyString(&(newDtd->pool), oldE->name);
+    if (!name)
+      return 0;
+    newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
+    if (!newE)
+      return 0;
+    if (oldE->nDefaultAtts) {
+      newE->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+      if (!newE->defaultAtts)
+        return 0;
+    }
+    if (oldE->idAtt)
+      newE->idAtt = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
+    newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
+    if (oldE->prefix)
+      newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldE->prefix->name, 0);
+    for (i = 0; i < newE->nDefaultAtts; i++) {
+      newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
+      newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
+      if (oldE->defaultAtts[i].value) {
+        newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
+        if (!newE->defaultAtts[i].value)
+          return 0;
+      }
+      else
+        newE->defaultAtts[i].value = 0;
+    }
+  }
+
+  /* Copy the entity tables. */
+  if (!copyEntityTable(&(newDtd->generalEntities),
+                       &(newDtd->pool),
+                       &(oldDtd->generalEntities), parser))
+      return 0;
+
+#ifdef XML_DTD
+  if (!copyEntityTable(&(newDtd->paramEntities),
+                       &(newDtd->pool),
+                       &(oldDtd->paramEntities), parser))
+      return 0;
+#endif /* XML_DTD */
+
+  newDtd->complete = oldDtd->complete;
+  newDtd->standalone = oldDtd->standalone;
+
+  /* Don't want deep copying for scaffolding */
+  newDtd->in_eldecl = oldDtd->in_eldecl;
+  newDtd->scaffold = oldDtd->scaffold;
+  newDtd->contentStringLen = oldDtd->contentStringLen;
+  newDtd->scaffSize = oldDtd->scaffSize;
+  newDtd->scaffLevel = oldDtd->scaffLevel;
+  newDtd->scaffIndex = oldDtd->scaffIndex;
+
+  return 1;
+}  /* End dtdCopy */
+
+static int copyEntityTable(HASH_TABLE *newTable,
+                           STRING_POOL *newPool,
+                           const HASH_TABLE *oldTable,
+                           XML_Parser parser)
+{
+  HASH_TABLE_ITER iter;
+  const XML_Char *cachedOldBase = 0;
+  const XML_Char *cachedNewBase = 0;
+  itkExpatUnused(parser);
+
+  hashTableIterInit(&iter, oldTable);
+
+  for (;;) {
+    ENTITY *newE;
+    const XML_Char *name;
+    const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
+    if (!oldE)
+      break;
+    name = poolCopyString(newPool, oldE->name);
+    if (!name)
+      return 0;
+    newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
+    if (!newE)
+      return 0;
+    if (oldE->systemId) {
+      const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
+      if (!tem)
+        return 0;
+      newE->systemId = tem;
+      if (oldE->base) {
+        if (oldE->base == cachedOldBase)
+          newE->base = cachedNewBase;
+        else {
+          cachedOldBase = oldE->base;
+          tem = poolCopyString(newPool, cachedOldBase);
+          if (!tem)
+            return 0;
+          cachedNewBase = newE->base = tem;
+        }
+      }
+    }
+    else {
+      const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
+      if (!tem)
+        return 0;
+      newE->textPtr = tem;
+      newE->textLen = oldE->textLen;
+    }
+    if (oldE->notation) {
+      const XML_Char *tem = poolCopyString(newPool, oldE->notation);
+      if (!tem)
+        return 0;
+      newE->notation = tem;
+    }
+  }
+  return 1;
+}
+
+#define INIT_SIZE 64
+
+static
+int keyeq(KEY s1, KEY s2)
+{
+  for (; *s1 == *s2; s1++, s2++)
+    if (*s1 == 0)
+      return 1;
+  return 0;
+}
+
+static
+unsigned long hash(KEY s)
+{
+  unsigned long h = 0;
+  while (*s)
+    h = (h << 5) + h + (unsigned char)*s++;
+  return h;
+}
+
+static
+NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
+{
+  size_t i;
+  if (table->size == 0) {
+    size_t tsize;
+
+    if (!createSize)
+      return 0;
+    tsize = INIT_SIZE * sizeof(NAMED *);
+    table->v = table->mem->malloc_fcn(tsize);
+    if (!table->v)
+      return 0;
+    memset(table->v, 0, tsize);
+    table->size = INIT_SIZE;
+    table->usedLim = INIT_SIZE / 2;
+    i = hash(name) & (table->size - 1);
+  }
+  else {
+    unsigned long h = hash(name);
+    for (i = h & (table->size - 1);
+         table->v[i];
+         i == 0 ? i = table->size - 1 : --i) {
+      if (keyeq(name, table->v[i]->name))
+        return table->v[i];
+    }
+    if (!createSize)
+      return 0;
+    if (table->used == table->usedLim) {
+      /* check for overflow */
+      size_t newSize = table->size * 2;
+      size_t tsize = newSize * sizeof(NAMED *);
+      NAMED **newV = table->mem->malloc_fcn(tsize);
+      if (!newV)
+        return 0;
+      memset(newV, 0, tsize);
+      for (i = 0; i < table->size; i++)
+        if (table->v[i]) {
+          size_t j;
+          for (j = hash(table->v[i]->name) & (newSize - 1);
+               newV[j];
+               j == 0 ? j = newSize - 1 : --j)
+            ;
+          newV[j] = table->v[i];
+        }
+      table->mem->free_fcn(table->v);
+      table->v = newV;
+      table->size = newSize;
+      table->usedLim = newSize/2;
+      for (i = h & (table->size - 1);
+           table->v[i];
+           i == 0 ? i = table->size - 1 : --i)
+        ;
+    }
+  }
+  table->v[i] = table->mem->malloc_fcn(createSize);
+  if (!table->v[i])
+    return 0;
+  memset(table->v[i], 0, createSize);
+  table->v[i]->name = name;
+  (table->used)++;
+  return table->v[i];
+}
+
+static
+void hashTableDestroy(HASH_TABLE *table)
+{
+  size_t i;
+  for (i = 0; i < table->size; i++) {
+    NAMED *p = table->v[i];
+    if (p)
+      table->mem->free_fcn(p);
+  }
+  if (table->v)
+    table->mem->free_fcn(table->v);
+}
+
+static
+void hashTableInit(HASH_TABLE *p, XML_Memory_Handling_Suite *ms)
+{
+  p->size = 0;
+  p->usedLim = 0;
+  p->used = 0;
+  p->v = 0;
+  p->mem = ms;
+}
+
+static
+void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
+{
+  iter->p = table->v;
+  iter->end = iter->p + table->size;
+}
+
+static
+NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
+{
+  while (iter->p != iter->end) {
+    NAMED *tem = *(iter->p)++;
+    if (tem)
+      return tem;
+  }
+  return 0;
+}
+
+
+static
+void poolInit(STRING_POOL *pool, XML_Memory_Handling_Suite *ms)
+{
+  pool->blocks = 0;
+  pool->freeBlocks = 0;
+  pool->start = 0;
+  pool->ptr = 0;
+  pool->end = 0;
+  pool->mem = ms;
+}
+
+static
+void poolClear(STRING_POOL *pool)
+{
+  if (!pool->freeBlocks)
+    pool->freeBlocks = pool->blocks;
+  else {
+    BLOCK *p = pool->blocks;
+    while (p) {
+      BLOCK *tem = p->next;
+      p->next = pool->freeBlocks;
+      pool->freeBlocks = p;
+      p = tem;
+    }
+  }
+  pool->blocks = 0;
+  pool->start = 0;
+  pool->ptr = 0;
+  pool->end = 0;
+}
+
+static
+void poolDestroy(STRING_POOL *pool)
+{
+  BLOCK *p = pool->blocks;
+  while (p) {
+    BLOCK *tem = p->next;
+    pool->mem->free_fcn(p);
+    p = tem;
+  }
+  pool->blocks = 0;
+  p = pool->freeBlocks;
+  while (p) {
+    BLOCK *tem = p->next;
+    pool->mem->free_fcn(p);
+    p = tem;
+  }
+  pool->freeBlocks = 0;
+  pool->ptr = 0;
+  pool->start = 0;
+  pool->end = 0;
+}
+
+static
+XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+                     const char *ptr, const char *end)
+{
+  if (!pool->ptr && !poolGrow(pool))
+    return 0;
+  for (;;) {
+    XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
+    if (ptr == end)
+      break;
+    if (!poolGrow(pool))
+      return 0;
+  }
+  return pool->start;
+}
+
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
+{
+  do {
+    if (!poolAppendChar(pool, *s))
+      return 0;
+  } while (*s++);
+  s = pool->start;
+  poolFinish(pool);
+  return s;
+}
+
+static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
+{
+  if (!pool->ptr && !poolGrow(pool))
+    return 0;
+  for (; n > 0; --n, s++) {
+    if (!poolAppendChar(pool, *s))
+      return 0;
+
+  }
+  s = pool->start;
+  poolFinish(pool);
+  return s;
+}
+
+static
+const XML_Char *poolAppendString(STRING_POOL *pool, const XML_Char *s)
+{
+  while (*s) {
+    if (!poolAppendChar(pool, *s))
+      return 0;
+    s++;
+  } 
+  return pool->start;
+}  /* End poolAppendString */
+
+static
+XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+                          const char *ptr, const char *end)
+{
+  if (!poolAppend(pool, enc, ptr, end))
+    return 0;
+  if (pool->ptr == pool->end && !poolGrow(pool))
+    return 0;
+  *(pool->ptr)++ = 0;
+  return pool->start;
+}
+
+static
+int poolGrow(STRING_POOL *pool)
+{
+  if (pool->freeBlocks) {
+    if (pool->start == 0) {
+      pool->blocks = pool->freeBlocks;
+      pool->freeBlocks = pool->freeBlocks->next;
+      pool->blocks->next = 0;
+      pool->start = pool->blocks->s;
+      pool->end = pool->start + pool->blocks->size;
+      pool->ptr = pool->start;
+      return 1;
+    }
+    if (pool->end - pool->start < pool->freeBlocks->size) {
+      BLOCK *tem = pool->freeBlocks->next;
+      pool->freeBlocks->next = pool->blocks;
+      pool->blocks = pool->freeBlocks;
+      pool->freeBlocks = tem;
+      memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char));
+      pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+      pool->start = pool->blocks->s;
+      pool->end = pool->start + pool->blocks->size;
+      return 1;
+    }
+  }
+  if (pool->blocks && pool->start == pool->blocks->s) {
+    int blockSize = (pool->end - pool->start)*2;
+    pool->blocks = pool->mem->realloc_fcn(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
+    if (!pool->blocks)
+      return 0;
+    pool->blocks->size = blockSize;
+    pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+    pool->start = pool->blocks->s;
+    pool->end = pool->start + blockSize;
+  }
+  else {
+    BLOCK *tem;
+    int blockSize = pool->end - pool->start;
+    if (blockSize < INIT_BLOCK_SIZE)
+      blockSize = INIT_BLOCK_SIZE;
+    else
+      blockSize *= 2;
+    tem = pool->mem->malloc_fcn(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
+    if (!tem)
+      return 0;
+    tem->size = blockSize;
+    tem->next = pool->blocks;
+    pool->blocks = tem;
+    if (pool->ptr != pool->start)
+      memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
+    pool->ptr = tem->s + (pool->ptr - pool->start);
+    pool->start = tem->s;
+    pool->end = tem->s + blockSize;
+  }
+  return 1;
+}
+
+static int
+nextScaffoldPart(XML_Parser parser)
+{
+  CONTENT_SCAFFOLD * me;
+  int next;
+
+  if (! dtd.scaffIndex) {
+    dtd.scaffIndex = MALLOC(groupSize * sizeof(int));
+    if (! dtd.scaffIndex)
+      return -1;
+    dtd.scaffIndex[0] = 0;
+  }
+
+  if (dtd.scaffCount >= dtd.scaffSize) {
+    if (dtd.scaffold) {
+      dtd.scaffSize *= 2;
+      dtd.scaffold = (CONTENT_SCAFFOLD *) REALLOC(dtd.scaffold,
+                                              dtd.scaffSize * sizeof(CONTENT_SCAFFOLD));
+    }
+    else {
+      dtd.scaffSize = 32;
+      dtd.scaffold = (CONTENT_SCAFFOLD *) MALLOC(dtd.scaffSize * sizeof(CONTENT_SCAFFOLD));
+    }
+    if (! dtd.scaffold)
+      return -1;
+  }
+  next = dtd.scaffCount++;
+  me = &dtd.scaffold[next];
+  if (dtd.scaffLevel) { 
+    CONTENT_SCAFFOLD *parent = &dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]];
+    if (parent->lastchild) {
+      dtd.scaffold[parent->lastchild].nextsib = next;
+    }
+    if (! parent->childcnt)
+      parent->firstchild = next;
+    parent->lastchild = next;
+    parent->childcnt++;
+  }
+  me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
+  return next;
+}  /* End nextScaffoldPart */
+
+static void
+build_node (XML_Parser parser,
+            int src_node,
+            XML_Content *dest,
+            XML_Content **contpos,
+            char **strpos)
+{
+  dest->type = dtd.scaffold[src_node].type;
+  dest->quant = dtd.scaffold[src_node].quant;
+  if (dest->type == XML_CTYPE_NAME) {
+    const char *src;
+    dest->name = *strpos;
+    src = dtd.scaffold[src_node].name;
+    for (;;) {
+      *(*strpos)++ = *src;
+      if (! *src)
+        break;
+      src++;
+    }
+    dest->numchildren = 0;
+    dest->children = 0;
+  }
+  else {
+    unsigned int i;
+    int cn;
+    dest->numchildren = dtd.scaffold[src_node].childcnt;
+    dest->children = *contpos;
+    *contpos += dest->numchildren;
+    for (i = 0, cn = dtd.scaffold[src_node].firstchild;
+         i < dest->numchildren;
+         i++, cn = dtd.scaffold[cn].nextsib) {
+      build_node(parser, cn, &(dest->children[i]), contpos, strpos);
+    }
+    dest->name = 0;
+  }
+}  /* End build_node */
+
+static XML_Content *
+build_model (XML_Parser parser)
+{
+  XML_Content *ret;
+  XML_Content *cpos;
+  char * str;
+  int allocsize = dtd.scaffCount * sizeof(XML_Content) + dtd.contentStringLen;
+  
+  ret = MALLOC(allocsize);
+  if (! ret)
+    return 0;
+
+  str =  (char *) (&ret[dtd.scaffCount]);
+  cpos = &ret[1];
+
+  build_node(parser, 0, ret, &cpos, &str);
+  return ret;
+}  /* End build_model */
+
+static ELEMENT_TYPE *
+getElementType(XML_Parser parser,
+               const ENCODING *enc,
+               const char *ptr,
+               const char *end)
+{
+  const XML_Char *name = poolStoreString(&dtd.pool, enc, ptr, end);
+  ELEMENT_TYPE *ret;
+
+  if (! name)
+    return 0;
+  ret = (ELEMENT_TYPE *) lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
+  if (! ret)
+    return 0;
+  if (ret->name != name)
+    poolDiscard(&dtd.pool);
+  else {
+    poolFinish(&dtd.pool);
+    if (!setElementTypePrefix(parser, ret))
+      return 0;
+  }
+  return ret;
+}  /* End getElementType */
diff --git a/Utilities/ITK/Utilities/expat/xmlrole.c b/Utilities/ITK/Utilities/expat/xmlrole.c
new file mode 100644
index 0000000000000000000000000000000000000000..c4da174353fe5b05ddfdee4d5d0a47a718de44d1
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/xmlrole.c
@@ -0,0 +1,1400 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+static char RCSId[]
+  = "$Header: /cvsroot/Insight/Insight/Utilities/expat/xmlrole.c,v 1.3 2006/02/02 23:05:33 malaterre Exp $";
+const char* GetVTKEXpatXMLRole_RCSId(void)
+{
+  return RCSId;
+}
+
+#include "expatConfig.h"
+
+#include "xmlrole.h"
+#include "ascii.h"
+
+/* Doesn't check:
+
+ that ,| are not mixed in a model group
+ content of literals
+
+*/
+
+static const char KW_ANY[] = { ASCII_A, ASCII_N, ASCII_Y, '\0' };
+static const char KW_ATTLIST[] = { ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' };
+static const char KW_CDATA[] = { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_DOCTYPE[] = { ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' };
+static const char KW_ELEMENT[] = { ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' };
+static const char KW_EMPTY[] = { ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' };
+static const char KW_ENTITIES[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
+static const char KW_ENTITY[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
+static const char KW_FIXED[] = { ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' };
+static const char KW_ID[] = { ASCII_I, ASCII_D, '\0' };
+static const char KW_IDREF[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
+static const char KW_IDREFS[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
+static const char KW_IGNORE[] = { ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' };
+static const char KW_IMPLIED[] = { ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' };
+static const char KW_INCLUDE[] = { ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' };
+static const char KW_NDATA[] = { ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_NMTOKEN[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
+static const char KW_NMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
+static const char KW_NOTATION[] = { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, '\0' };
+static const char KW_PCDATA[] = { ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_PUBLIC[] = { ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' };
+static const char KW_REQUIRED[] = { ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D, '\0' };
+static const char KW_SYSTEM[] = { ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' };
+
+#ifndef MIN_BYTES_PER_CHAR
+#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
+#endif
+
+#ifdef XML_DTD
+#define setTopLevel(state) \
+  ((state)->handler = ((state)->documentEntity \
+                       ? internalSubset \
+                       : externalSubset1))
+#else /* not XML_DTD */
+#define setTopLevel(state) ((state)->handler = internalSubset)
+#endif /* not XML_DTD */
+
+typedef int PROLOG_HANDLER(PROLOG_STATE *state,
+                           int tok,
+                           const char *ptr,
+                           const char *end,
+                           const ENCODING *enc);
+
+static PROLOG_HANDLER
+  prolog0, prolog1, prolog2,
+  doctype0, doctype1, doctype2, doctype3, doctype4, doctype5,
+  internalSubset,
+  entity0, entity1, entity2, entity3, entity4, entity5, entity6,
+  entity7, entity8, entity9,
+  notation0, notation1, notation2, notation3, notation4,
+  attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6,
+  attlist7, attlist8, attlist9,
+  element0, element1, element2, element3, element4, element5, element6,
+  element7,
+#ifdef XML_DTD
+  externalSubset0, externalSubset1,
+  condSect0, condSect1, condSect2,
+#endif /* XML_DTD */
+  declClose,
+  error;
+
+static
+int common(PROLOG_STATE *state, int tok);
+
+static
+int prolog0(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    state->handler = prolog1;
+    return XML_ROLE_NONE;
+  case XML_TOK_XML_DECL:
+    state->handler = prolog1;
+    return XML_ROLE_XML_DECL;
+  case XML_TOK_PI:
+    state->handler = prolog1;
+    return XML_ROLE_NONE;
+  case XML_TOK_COMMENT:
+    state->handler = prolog1;
+  case XML_TOK_BOM:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_OPEN:
+    if (!XmlNameMatchesAscii(enc,
+                             ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                             end,
+                             KW_DOCTYPE))
+      break;
+    state->handler = doctype0;
+    return XML_ROLE_NONE;
+  case XML_TOK_INSTANCE_START:
+    state->handler = error;
+    return XML_ROLE_INSTANCE_START;
+  }
+  return common(state, tok);
+}
+
+static
+int prolog1(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_PI:
+  case XML_TOK_COMMENT:
+  case XML_TOK_BOM:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_OPEN:
+    if (!XmlNameMatchesAscii(enc,
+                             ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                             end,
+                             KW_DOCTYPE))
+      break;
+    state->handler = doctype0;
+    return XML_ROLE_NONE;
+  case XML_TOK_INSTANCE_START:
+    state->handler = error;
+    return XML_ROLE_INSTANCE_START;
+  }
+  return common(state, tok);
+}
+
+static
+int prolog2(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_PI:
+  case XML_TOK_COMMENT:
+    return XML_ROLE_NONE;
+  case XML_TOK_INSTANCE_START:
+    state->handler = error;
+    return XML_ROLE_INSTANCE_START;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype0(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = doctype1;
+    return XML_ROLE_DOCTYPE_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype1(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_BRACKET:
+    state->handler = internalSubset;
+    return XML_ROLE_DOCTYPE_INTERNAL_SUBSET;
+  case XML_TOK_DECL_CLOSE:
+    state->handler = prolog2;
+    return XML_ROLE_DOCTYPE_CLOSE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+      state->handler = doctype3;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+      state->handler = doctype2;
+      return XML_ROLE_NONE;
+    }
+    break;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype2(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = doctype3;
+    return XML_ROLE_DOCTYPE_PUBLIC_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype3(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = doctype4;
+    return XML_ROLE_DOCTYPE_SYSTEM_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype4(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_BRACKET:
+    state->handler = internalSubset;
+    return XML_ROLE_DOCTYPE_INTERNAL_SUBSET;
+  case XML_TOK_DECL_CLOSE:
+    state->handler = prolog2;
+    return XML_ROLE_DOCTYPE_CLOSE;
+  }
+  return common(state, tok);
+}
+
+static
+int doctype5(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_CLOSE:
+    state->handler = prolog2;
+    return XML_ROLE_DOCTYPE_CLOSE;
+  }
+  return common(state, tok);
+}
+
+static
+int internalSubset(PROLOG_STATE *state,
+                   int tok,
+                   const char *ptr,
+                   const char *end,
+                   const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_OPEN:
+    if (XmlNameMatchesAscii(enc,
+                            ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                            end,
+                            KW_ENTITY)) {
+      state->handler = entity0;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc,
+                            ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                            end,
+                            KW_ATTLIST)) {
+      state->handler = attlist0;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc,
+                            ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                            end,
+                            KW_ELEMENT)) {
+      state->handler = element0;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc,
+                            ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+                            end,
+                            KW_NOTATION)) {
+      state->handler = notation0;
+      return XML_ROLE_NONE;
+    }
+    break;
+  case XML_TOK_PI:
+  case XML_TOK_COMMENT:
+    return XML_ROLE_NONE;
+  case XML_TOK_PARAM_ENTITY_REF:
+    return XML_ROLE_PARAM_ENTITY_REF;
+  case XML_TOK_CLOSE_BRACKET:
+    state->handler = doctype5;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+#ifdef XML_DTD
+
+static
+int externalSubset0(PROLOG_STATE *state,
+                    int tok,
+                    const char *ptr,
+                    const char *end,
+                    const ENCODING *enc)
+{
+  state->handler = externalSubset1;
+  if (tok == XML_TOK_XML_DECL)
+    return XML_ROLE_TEXT_DECL;
+  return externalSubset1(state, tok, ptr, end, enc);
+}
+
+static
+int externalSubset1(PROLOG_STATE *state,
+                    int tok,
+                    const char *ptr,
+                    const char *end,
+                    const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_COND_SECT_OPEN:
+    state->handler = condSect0;
+    return XML_ROLE_NONE;
+  case XML_TOK_COND_SECT_CLOSE:
+    if (state->includeLevel == 0)
+      break;
+    state->includeLevel -= 1;
+    return XML_ROLE_NONE;
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_BRACKET:
+    break;
+  case XML_TOK_NONE:
+    if (state->includeLevel)
+      break;
+    return XML_ROLE_NONE;
+  default:
+    return internalSubset(state, tok, ptr, end, enc);
+  }
+  return common(state, tok);
+}
+
+#endif /* XML_DTD */
+
+static
+int entity0(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_PERCENT:
+    state->handler = entity1;
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    state->handler = entity2;
+    return XML_ROLE_GENERAL_ENTITY_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int entity1(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    state->handler = entity7;
+    return XML_ROLE_PARAM_ENTITY_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int entity2(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+      state->handler = entity4;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+      state->handler = entity3;
+      return XML_ROLE_NONE;
+    }
+    break;
+  case XML_TOK_LITERAL:
+    state->handler = declClose;
+    return XML_ROLE_ENTITY_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int entity3(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = entity4;
+    return XML_ROLE_ENTITY_PUBLIC_ID;
+  }
+  return common(state, tok);
+}
+
+
+static
+int entity4(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = entity5;
+    return XML_ROLE_ENTITY_SYSTEM_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int entity5(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_CLOSE:
+    setTopLevel(state);
+    return XML_ROLE_ENTITY_COMPLETE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) {
+      state->handler = entity6;
+      return XML_ROLE_NONE;
+    }
+    break;
+  }
+  return common(state, tok);
+}
+
+static
+int entity6(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    state->handler = declClose;
+    return XML_ROLE_ENTITY_NOTATION_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int entity7(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+      state->handler = entity9;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+      state->handler = entity8;
+      return XML_ROLE_NONE;
+    }
+    break;
+  case XML_TOK_LITERAL:
+    state->handler = declClose;
+    return XML_ROLE_ENTITY_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int entity8(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = entity9;
+    return XML_ROLE_ENTITY_PUBLIC_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int entity9(PROLOG_STATE *state,
+            int tok,
+            const char *ptr,
+            const char *end,
+            const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = declClose;
+    return XML_ROLE_ENTITY_SYSTEM_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int notation0(PROLOG_STATE *state,
+              int tok,
+              const char *ptr,
+              const char *end,
+              const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    state->handler = notation1;
+    return XML_ROLE_NOTATION_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int notation1(PROLOG_STATE *state,
+              int tok,
+              const char *ptr,
+              const char *end,
+              const ENCODING *enc)
+{
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+      state->handler = notation3;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+      state->handler = notation2;
+      return XML_ROLE_NONE;
+    }
+    break;
+  }
+  return common(state, tok);
+}
+
+static
+int notation2(PROLOG_STATE *state,
+              int tok,
+              const char *ptr,
+              const char *end,
+              const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = notation4;
+    return XML_ROLE_NOTATION_PUBLIC_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int notation3(PROLOG_STATE *state,
+              int tok,
+              const char *ptr,
+              const char *end,
+              const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = declClose;
+    return XML_ROLE_NOTATION_SYSTEM_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int notation4(PROLOG_STATE *state,
+              int tok,
+              const char *ptr,
+              const char *end,
+              const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = declClose;
+    return XML_ROLE_NOTATION_SYSTEM_ID;
+  case XML_TOK_DECL_CLOSE:
+    setTopLevel(state);
+    return XML_ROLE_NOTATION_NO_SYSTEM_ID;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist0(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = attlist1;
+    return XML_ROLE_ATTLIST_ELEMENT_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist1(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_CLOSE:
+    setTopLevel(state);
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = attlist2;
+    return XML_ROLE_ATTRIBUTE_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist2(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    {
+      static const char *types[] = {
+        KW_CDATA,
+        KW_ID,
+        KW_IDREF,
+        KW_IDREFS,
+        KW_ENTITY,
+        KW_ENTITIES,
+        KW_NMTOKEN,
+        KW_NMTOKENS,
+      };
+      int i;
+      for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++)
+        if (XmlNameMatchesAscii(enc, ptr, end, types[i])) {
+          state->handler = attlist8;
+          return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i;
+        }
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) {
+      state->handler = attlist5;
+      return XML_ROLE_NONE;
+    }
+    break;
+  case XML_TOK_OPEN_PAREN:
+    state->handler = attlist3;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist3(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NMTOKEN:
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = attlist4;
+    return XML_ROLE_ATTRIBUTE_ENUM_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist4(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_PAREN:
+    state->handler = attlist8;
+    return XML_ROLE_NONE;
+  case XML_TOK_OR:
+    state->handler = attlist3;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist5(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_PAREN:
+    state->handler = attlist6;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+
+static
+int attlist6(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    state->handler = attlist7;
+    return XML_ROLE_ATTRIBUTE_NOTATION_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist7(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_PAREN:
+    state->handler = attlist8;
+    return XML_ROLE_NONE;
+  case XML_TOK_OR:
+    state->handler = attlist6;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+/* default value */
+static
+int attlist8(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_POUND_NAME:
+    if (XmlNameMatchesAscii(enc,
+                            ptr + MIN_BYTES_PER_CHAR(enc),
+                            end,
+                            KW_IMPLIED)) {
+      state->handler = attlist1;
+      return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE;
+    }
+    if (XmlNameMatchesAscii(enc,
+                            ptr + MIN_BYTES_PER_CHAR(enc),
+                            end,
+                            KW_REQUIRED)) {
+      state->handler = attlist1;
+      return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE;
+    }
+    if (XmlNameMatchesAscii(enc,
+                            ptr + MIN_BYTES_PER_CHAR(enc),
+                            end,
+                            KW_FIXED)) {
+      state->handler = attlist9;
+      return XML_ROLE_NONE;
+    }
+    break;
+  case XML_TOK_LITERAL:
+    state->handler = attlist1;
+    return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int attlist9(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_LITERAL:
+    state->handler = attlist1;
+    return XML_ROLE_FIXED_ATTRIBUTE_VALUE;
+  }
+  return common(state, tok);
+}
+
+static
+int element0(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = element1;
+    return XML_ROLE_ELEMENT_NAME;
+  }
+  return common(state, tok);
+}
+
+static
+int element1(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) {
+      state->handler = declClose;
+      return XML_ROLE_CONTENT_EMPTY;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) {
+      state->handler = declClose;
+      return XML_ROLE_CONTENT_ANY;
+    }
+    break;
+  case XML_TOK_OPEN_PAREN:
+    state->handler = element2;
+    state->level = 1;
+    return XML_ROLE_GROUP_OPEN;
+  }
+  return common(state, tok);
+}
+
+static
+int element2(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_POUND_NAME:
+    if (XmlNameMatchesAscii(enc,
+                            ptr + MIN_BYTES_PER_CHAR(enc),
+                            end,
+                            KW_PCDATA)) {
+      state->handler = element3;
+      return XML_ROLE_CONTENT_PCDATA;
+    }
+    break;
+  case XML_TOK_OPEN_PAREN:
+    state->level = 2;
+    state->handler = element6;
+    return XML_ROLE_GROUP_OPEN;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT;
+  case XML_TOK_NAME_QUESTION:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_OPT;
+  case XML_TOK_NAME_ASTERISK:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_REP;
+  case XML_TOK_NAME_PLUS:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_PLUS;
+  }
+  return common(state, tok);
+}
+
+static
+int element3(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_PAREN:
+    state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE;
+  case XML_TOK_CLOSE_PAREN_ASTERISK:
+    state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE_REP;
+  case XML_TOK_OR:
+    state->handler = element4;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+static
+int element4(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = element5;
+    return XML_ROLE_CONTENT_ELEMENT;
+  }
+  return common(state, tok);
+}
+
+static
+int element5(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_PAREN_ASTERISK:
+    state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE_REP;
+  case XML_TOK_OR:
+    state->handler = element4;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+static
+int element6(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_PAREN:
+    state->level += 1;
+    return XML_ROLE_GROUP_OPEN;
+  case XML_TOK_NAME:
+  case XML_TOK_PREFIXED_NAME:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT;
+  case XML_TOK_NAME_QUESTION:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_OPT;
+  case XML_TOK_NAME_ASTERISK:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_REP;
+  case XML_TOK_NAME_PLUS:
+    state->handler = element7;
+    return XML_ROLE_CONTENT_ELEMENT_PLUS;
+  }
+  return common(state, tok);
+}
+
+static
+int element7(PROLOG_STATE *state,
+             int tok,
+             const char *ptr,
+             const char *end,
+             const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_CLOSE_PAREN:
+    state->level -= 1;
+    if (state->level == 0)
+      state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE;
+  case XML_TOK_CLOSE_PAREN_ASTERISK:
+    state->level -= 1;
+    if (state->level == 0)
+      state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE_REP;
+  case XML_TOK_CLOSE_PAREN_QUESTION:
+    state->level -= 1;
+    if (state->level == 0)
+      state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE_OPT;
+  case XML_TOK_CLOSE_PAREN_PLUS:
+    state->level -= 1;
+    if (state->level == 0)
+      state->handler = declClose;
+    return XML_ROLE_GROUP_CLOSE_PLUS;
+  case XML_TOK_COMMA:
+    state->handler = element6;
+    return XML_ROLE_GROUP_SEQUENCE;
+  case XML_TOK_OR:
+    state->handler = element6;
+    return XML_ROLE_GROUP_CHOICE;
+  }
+  return common(state, tok);
+}
+
+#ifdef XML_DTD
+
+static
+int condSect0(PROLOG_STATE *state,
+              int tok,
+              const char *ptr,
+              const char *end,
+              const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_NAME:
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) {
+      state->handler = condSect1;
+      return XML_ROLE_NONE;
+    }
+    if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) {
+      state->handler = condSect2;
+      return XML_ROLE_NONE;
+    }
+    break;
+  }
+  return common(state, tok);
+}
+
+static
+int condSect1(PROLOG_STATE *state,
+              int tok,
+              const char *ptr,
+              const char *end,
+              const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_BRACKET:
+    state->handler = externalSubset1;
+    state->includeLevel += 1;
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+static
+int condSect2(PROLOG_STATE *state,
+              int tok,
+              const char *ptr,
+              const char *end,
+              const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_OPEN_BRACKET:
+    state->handler = externalSubset1;
+    return XML_ROLE_IGNORE_SECT;
+  }
+  return common(state, tok);
+}
+
+#endif /* XML_DTD */
+
+static
+int declClose(PROLOG_STATE *state,
+              int tok,
+              const char *ptr,
+              const char *end,
+              const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_PROLOG_S:
+    return XML_ROLE_NONE;
+  case XML_TOK_DECL_CLOSE:
+    setTopLevel(state);
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+
+#if 0
+
+static
+int ignore(PROLOG_STATE *state,
+           int tok,
+           const char *ptr,
+           const char *end,
+           const ENCODING *enc)
+{
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  switch (tok) {
+  case XML_TOK_DECL_CLOSE:
+    state->handler = internalSubset;
+    return 0;
+  default:
+    return XML_ROLE_NONE;
+  }
+  return common(state, tok);
+}
+#endif
+
+static
+int error(PROLOG_STATE *state,
+          int tok,
+          const char *ptr,
+          const char *end,
+          const ENCODING *enc)
+{
+  itkExpatUnused(state);
+  itkExpatUnused(tok);
+  itkExpatUnused(ptr);
+  itkExpatUnused(end);
+  itkExpatUnused(enc);
+  return XML_ROLE_NONE;
+}
+
+static
+int common(PROLOG_STATE *state, int tok)
+{
+#ifdef XML_DTD
+  if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF)
+    return XML_ROLE_INNER_PARAM_ENTITY_REF;
+#endif
+  state->handler = error;
+  return XML_ROLE_ERROR;
+}
+
+void XmlPrologStateInit(PROLOG_STATE *state)
+{
+  state->handler = prolog0;
+#ifdef XML_DTD
+  state->documentEntity = 1;
+  state->includeLevel = 0;
+#endif /* XML_DTD */
+}
+
+#ifdef XML_DTD
+
+void XmlPrologStateInitExternalEntity(PROLOG_STATE *state)
+{
+  state->handler = externalSubset0;
+  state->documentEntity = 0;
+  state->includeLevel = 0;
+}
+
+#endif /* XML_DTD */
diff --git a/Utilities/ITK/Utilities/expat/xmlrole.h b/Utilities/ITK/Utilities/expat/xmlrole.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f257930666685466fa41dac6d8aa654079c46e4
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/xmlrole.h
@@ -0,0 +1,100 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#ifndef XmlRole_INCLUDED
+#define XmlRole_INCLUDED 1
+
+#include "xmltok.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+  XML_ROLE_ERROR = -1,
+  XML_ROLE_NONE = 0,
+  XML_ROLE_XML_DECL,
+  XML_ROLE_INSTANCE_START,
+  XML_ROLE_DOCTYPE_NAME,
+  XML_ROLE_DOCTYPE_SYSTEM_ID,
+  XML_ROLE_DOCTYPE_PUBLIC_ID,
+  XML_ROLE_DOCTYPE_INTERNAL_SUBSET,
+  XML_ROLE_DOCTYPE_CLOSE,
+  XML_ROLE_GENERAL_ENTITY_NAME,
+  XML_ROLE_PARAM_ENTITY_NAME,
+  XML_ROLE_ENTITY_VALUE,
+  XML_ROLE_ENTITY_SYSTEM_ID,
+  XML_ROLE_ENTITY_PUBLIC_ID,
+  XML_ROLE_ENTITY_COMPLETE,
+  XML_ROLE_ENTITY_NOTATION_NAME,
+  XML_ROLE_NOTATION_NAME,
+  XML_ROLE_NOTATION_SYSTEM_ID,
+  XML_ROLE_NOTATION_NO_SYSTEM_ID,
+  XML_ROLE_NOTATION_PUBLIC_ID,
+  XML_ROLE_ATTRIBUTE_NAME,
+  XML_ROLE_ATTRIBUTE_TYPE_CDATA,
+  XML_ROLE_ATTRIBUTE_TYPE_ID,
+  XML_ROLE_ATTRIBUTE_TYPE_IDREF,
+  XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
+  XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
+  XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
+  XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
+  XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
+  XML_ROLE_ATTRIBUTE_ENUM_VALUE,
+  XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
+  XML_ROLE_ATTLIST_ELEMENT_NAME,
+  XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
+  XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
+  XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
+  XML_ROLE_FIXED_ATTRIBUTE_VALUE,
+  XML_ROLE_ELEMENT_NAME,
+  XML_ROLE_CONTENT_ANY,
+  XML_ROLE_CONTENT_EMPTY,
+  XML_ROLE_CONTENT_PCDATA,
+  XML_ROLE_GROUP_OPEN,
+  XML_ROLE_GROUP_CLOSE,
+  XML_ROLE_GROUP_CLOSE_REP,
+  XML_ROLE_GROUP_CLOSE_OPT,
+  XML_ROLE_GROUP_CLOSE_PLUS,
+  XML_ROLE_GROUP_CHOICE,
+  XML_ROLE_GROUP_SEQUENCE,
+  XML_ROLE_CONTENT_ELEMENT,
+  XML_ROLE_CONTENT_ELEMENT_REP,
+  XML_ROLE_CONTENT_ELEMENT_OPT,
+  XML_ROLE_CONTENT_ELEMENT_PLUS,
+#ifdef XML_DTD
+  XML_ROLE_TEXT_DECL,
+  XML_ROLE_IGNORE_SECT,
+  XML_ROLE_INNER_PARAM_ENTITY_REF,
+#endif /* XML_DTD */
+  XML_ROLE_PARAM_ENTITY_REF
+};
+
+typedef struct prolog_state {
+  int (*handler)(struct prolog_state *state,
+                 int tok,
+                 const char *ptr,
+                 const char *end,
+                 const ENCODING *enc);
+  unsigned level;
+#ifdef XML_DTD
+  unsigned includeLevel;
+  int documentEntity;
+#endif /* XML_DTD */
+} PROLOG_STATE;
+
+void XmlPrologStateInit(PROLOG_STATE *);
+#ifdef XML_DTD
+void XmlPrologStateInitExternalEntity(PROLOG_STATE *);
+#endif /* XML_DTD */
+
+#define XmlTokenRole(state, tok, ptr, end, enc) \
+ (((state)->handler)(state, tok, ptr, end, enc))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlRole_INCLUDED */
diff --git a/Utilities/ITK/Utilities/expat/xmltok.c b/Utilities/ITK/Utilities/expat/xmltok.c
new file mode 100644
index 0000000000000000000000000000000000000000..1a6c6538d19f436b7b36e7b17d45bc246973df5a
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/xmltok.c
@@ -0,0 +1,1584 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#include "expatConfig.h"
+
+#include "xmltok.h"
+#include "nametab.h"
+
+#if defined(__BORLANDC__)
+#pragma warn -8008 // Disable "condition is always true" warning.
+#pragma warn -8066 // Disable "unreachable code" warning.
+#endif
+
+#ifdef XML_DTD
+#define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
+#else
+#define IGNORE_SECTION_TOK_VTABLE /* as nothing */
+#endif
+
+#define VTABLE1 \
+  { PREFIX(prologTok), PREFIX(contentTok), \
+    PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \
+  { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
+  PREFIX(sameName), \
+  PREFIX(nameMatchesAscii), \
+  PREFIX(nameLength), \
+  PREFIX(skipS), \
+  PREFIX(getAtts), \
+  PREFIX(charRefNumber), \
+  PREFIX(predefinedEntityName), \
+  PREFIX(updatePosition), \
+  PREFIX(isPublicId)
+
+#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
+
+#define UCS2_GET_NAMING(pages, hi, lo) \
+   (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F)))
+
+/* A 2 byte UTF-8 representation splits the characters 11 bits
+between the bottom 5 and 6 bits of the bytes.
+We need 8 bits to index into pages, 3 bits to add to that index and
+5 bits to generate the mask. */
+#define UTF8_GET_NAMING2(pages, byte) \
+    (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
+                      + ((((byte)[0]) & 3) << 1) \
+                      + ((((byte)[1]) >> 5) & 1)] \
+         & (1 << (((byte)[1]) & 0x1F)))
+
+/* A 3 byte UTF-8 representation splits the characters 16 bits
+between the bottom 4, 6 and 6 bits of the bytes.
+We need 8 bits to index into pages, 3 bits to add to that index and
+5 bits to generate the mask. */
+#define UTF8_GET_NAMING3(pages, byte) \
+  (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
+                             + ((((byte)[1]) >> 2) & 0xF)] \
+                       << 3) \
+                      + ((((byte)[1]) & 3) << 1) \
+                      + ((((byte)[2]) >> 5) & 1)] \
+         & (1 << (((byte)[2]) & 0x1F)))
+
+#define UTF8_GET_NAMING(pages, p, n) \
+  ((n) == 2 \
+  ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
+  : ((n) == 3 \
+     ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
+     : 0))
+
+#define UTF8_INVALID3(p) \
+  ((*p) == 0xED \
+  ? (((p)[1] & 0x20) != 0) \
+  : ((*p) == 0xEF \
+     ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \
+     : 0))
+
+#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0)
+
+static
+int isNever(const ENCODING *enc, const char *p)
+{
+  itkExpatUnused(enc);
+  itkExpatUnused(p);
+  return 0;
+}
+
+static
+int utf8_isName2(const ENCODING *enc, const char *p)
+{
+  itkExpatUnused(enc);
+  return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
+}
+
+static
+int utf8_isName3(const ENCODING *enc, const char *p)
+{
+  itkExpatUnused(enc);
+  return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
+}
+
+#define utf8_isName4 isNever
+
+static
+int utf8_isNmstrt2(const ENCODING *enc, const char *p)
+{
+  itkExpatUnused(enc);
+  return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
+}
+
+static
+int utf8_isNmstrt3(const ENCODING *enc, const char *p)
+{
+  itkExpatUnused(enc);
+  return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
+}
+
+#define utf8_isNmstrt4 isNever
+
+#define utf8_isInvalid2 isNever
+
+static
+int utf8_isInvalid3(const ENCODING *enc, const char *p)
+{
+  itkExpatUnused(enc);
+  return UTF8_INVALID3((const unsigned char *)p);
+}
+
+static
+int utf8_isInvalid4(const ENCODING *enc, const char *p)
+{
+  itkExpatUnused(enc);
+  return UTF8_INVALID4((const unsigned char *)p);
+}
+
+struct normal_encoding {
+  ENCODING enc;
+  unsigned char type[256];
+#ifdef XML_MIN_SIZE
+  int (*byteType)(const ENCODING *, const char *);
+  int (*isNameMin)(const ENCODING *, const char *);
+  int (*isNmstrtMin)(const ENCODING *, const char *);
+  int (*byteToAscii)(const ENCODING *, const char *);
+  int (*charMatches)(const ENCODING *, const char *, int);
+#endif /* XML_MIN_SIZE */
+  int (*isName2)(const ENCODING *, const char *);
+  int (*isName3)(const ENCODING *, const char *);
+  int (*isName4)(const ENCODING *, const char *);
+  int (*isNmstrt2)(const ENCODING *, const char *);
+  int (*isNmstrt3)(const ENCODING *, const char *);
+  int (*isNmstrt4)(const ENCODING *, const char *);
+  int (*isInvalid2)(const ENCODING *, const char *);
+  int (*isInvalid3)(const ENCODING *, const char *);
+  int (*isInvalid4)(const ENCODING *, const char *);
+};
+
+#ifdef XML_MIN_SIZE
+
+#define STANDARD_VTABLE(E) \
+ E ## byteType, \
+ E ## isNameMin, \
+ E ## isNmstrtMin, \
+ E ## byteToAscii, \
+ E ## charMatches,
+
+#else
+
+#define STANDARD_VTABLE(E) /* as nothing */
+
+#endif
+
+#define NORMAL_VTABLE(E) \
+ E ## isName2, \
+ E ## isName3, \
+ E ## isName4, \
+ E ## isNmstrt2, \
+ E ## isNmstrt3, \
+ E ## isNmstrt4, \
+ E ## isInvalid2, \
+ E ## isInvalid3, \
+ E ## isInvalid4
+
+#define EMPTY_VTABLE(E) 0, 0, 0, 0, 0, 0, 0, 0, 0
+
+static int checkCharRefNumber(int);
+
+#include "xmltok_impl.h"
+#include "ascii.h"
+
+#ifdef XML_MIN_SIZE
+#define sb_isNameMin isNever
+#define sb_isNmstrtMin isNever
+#endif
+
+#ifdef XML_MIN_SIZE
+#define MINBPC(enc) ((enc)->minBytesPerChar)
+#else
+/* minimum bytes per character */
+#define MINBPC(enc) 1
+#endif
+
+#define SB_BYTE_TYPE(enc, p) \
+  (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
+
+#ifdef XML_MIN_SIZE
+static
+int sb_byteType(const ENCODING *enc, const char *p)
+{
+  return SB_BYTE_TYPE(enc, p);
+}
+#define BYTE_TYPE(enc, p) \
+ (((const struct normal_encoding *)(enc))->byteType(enc, p))
+#else
+#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define BYTE_TO_ASCII(enc, p) \
+ (((const struct normal_encoding *)(enc))->byteToAscii(enc, p))
+static
+int sb_byteToAscii(const ENCODING *enc, const char *p)
+{
+  return *p;
+}
+#else
+#define BYTE_TO_ASCII(enc, p) (*(p))
+#endif
+
+#define IS_NAME_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isName ## n(enc, p))
+#define IS_NMSTRT_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p))
+#define IS_INVALID_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p))
+
+#ifdef XML_MIN_SIZE
+#define IS_NAME_CHAR_MINBPC(enc, p) \
+ (((const struct normal_encoding *)(enc))->isNameMin(enc, p))
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p))
+#else
+#define IS_NAME_CHAR_MINBPC(enc, p) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define CHAR_MATCHES(enc, p, c) \
+ (((const struct normal_encoding *)(enc))->charMatches(enc, p, c))
+static
+int sb_charMatches(const ENCODING *enc, const char *p, int c)
+{
+  return *p == c;
+}
+#else
+/* c is an ASCII character */
+#define CHAR_MATCHES(enc, p, c) (*(p) == c)
+#endif
+
+#define PREFIX(ident) normal_ ## ident
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+enum {  /* UTF8_cvalN is value of masked first byte of N byte sequence */
+  UTF8_cval1 = 0x00,
+  UTF8_cval2 = 0xc0,
+  UTF8_cval3 = 0xe0,
+  UTF8_cval4 = 0xf0
+};
+
+static
+void utf8_toUtf8(const ENCODING *enc,
+                 const char **fromP, const char *fromLim,
+                 char **toP, const char *toLim)
+{
+  char *to;
+  const char *from;
+  itkExpatUnused(enc);
+  if (fromLim - *fromP > toLim - *toP) {
+    /* Avoid copying partial characters. */
+    for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
+      if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
+        break;
+  }
+  for (to = *toP, from = *fromP; from != fromLim; from++, to++)
+    *to = *from;
+  *fromP = from;
+  *toP = to;
+}
+
+static
+void utf8_toUtf16(const ENCODING *enc,
+                  const char **fromP, const char *fromLim,
+                  unsigned short **toP, const unsigned short *toLim)
+{
+  unsigned short *to = *toP;
+  const char *from = *fromP;
+  while (from != fromLim && to != toLim) {
+    switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
+    case BT_LEAD2:
+      *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f);
+      from += 2;
+      break;
+    case BT_LEAD3:
+      *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f);
+      from += 3;
+      break;
+    case BT_LEAD4:
+      {
+        unsigned long n;
+        if (to + 1 == toLim)
+          break;
+        n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
+        n -= 0x10000;
+        to[0] = (unsigned short)((n >> 10) | 0xD800);
+        to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
+        to += 2;
+        from += 4;
+      }
+      break;
+    default:
+      *to++ = *from++;
+      break;
+    }
+  }
+  *fromP = from;
+  *toP = to;
+}
+
+#ifdef XML_NS
+static const struct normal_encoding utf8_encoding_ns = {
+  { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+  {
+#include "asciitab.h"
+#include "utf8tab.h"
+  },
+  STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+#endif
+
+static const struct normal_encoding utf8_encoding = {
+  { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+  },
+  STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_utf8_encoding_ns = {
+  { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+  {
+#include "iasciitab.h"
+#include "utf8tab.h"
+  },
+  STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#endif
+
+static const struct normal_encoding internal_utf8_encoding = {
+  { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+  },
+  STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+static
+void latin1_toUtf8(const ENCODING *enc,
+                   const char **fromP, const char *fromLim,
+                   char **toP, const char *toLim)
+{
+  itkExpatUnused(enc);
+  for (;;) {
+    unsigned char c;
+    if (*fromP == fromLim)
+      break;
+    c = (unsigned char)**fromP;
+    if (c & 0x80) {
+      if (toLim - *toP < 2)
+        break;
+      *(*toP)++ = ((c >> 6) | UTF8_cval2);
+      *(*toP)++ = ((c & 0x3f) | 0x80);
+      (*fromP)++;
+    }
+    else {
+      if (*toP == toLim)
+        break;
+      *(*toP)++ = *(*fromP)++;
+    }
+  }
+}
+
+static
+void latin1_toUtf16(const ENCODING *enc,
+                    const char **fromP, const char *fromLim,
+                    unsigned short **toP, const unsigned short *toLim)
+{
+  itkExpatUnused(enc);
+  while (*fromP != fromLim && *toP != toLim)
+    *(*toP)++ = (unsigned char)*(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding latin1_encoding_ns = {
+  { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+  {
+#include "asciitab.h"
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(sb_) EMPTY_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding latin1_encoding = {
+  { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(sb_) EMPTY_VTABLE(sb_)
+};
+
+static
+void ascii_toUtf8(const ENCODING *enc,
+                  const char **fromP, const char *fromLim,
+                  char **toP, const char *toLim)
+{
+  itkExpatUnused(enc);
+  while (*fromP != fromLim && *toP != toLim)
+    *(*toP)++ = *(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding ascii_encoding_ns = {
+  { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+  {
+#include "asciitab.h"
+/* BT_NONXML == 0 */
+  },
+  STANDARD_VTABLE(sb_) EMPTY_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding ascii_encoding = {
+  { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+/* BT_NONXML == 0 */
+  },
+  STANDARD_VTABLE(sb_) EMPTY_VTABLE(sb_)
+};
+
+static int unicode_byte_type(char hi, char lo)
+{
+  switch ((unsigned char)hi) {
+  case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+    return BT_LEAD4;
+  case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+    return BT_TRAIL;
+  case 0xFF:
+    switch ((unsigned char)lo) {
+    case 0xFF:
+    case 0xFE:
+      return BT_NONXML;
+    }
+    break;
+  }
+  return BT_NONASCII;
+}
+
+#define DEFINE_UTF16_TO_UTF8(E) \
+static \
+void E ## toUtf8(const ENCODING *enc, \
+                 const char **fromP, const char *fromLim, \
+                 char **toP, const char *toLim) \
+{ \
+  const char *from; \
+  itkExpatUnused(enc);\
+  for (from = *fromP; from != fromLim; from += 2) { \
+    int plane; \
+    unsigned char lo2; \
+    unsigned char lo = GET_LO(from); \
+    unsigned char hi = GET_HI(from); \
+    switch (hi) { \
+    case 0: \
+      if (lo < 0x80) { \
+        if (*toP == toLim) { \
+          *fromP = from; \
+          return; \
+        } \
+        *(*toP)++ = lo; \
+        break; \
+      } \
+      /* fall through */ \
+    case 0x1: case 0x2: case 0x3: \
+    case 0x4: case 0x5: case 0x6: case 0x7: \
+      if (toLim -  *toP < 2) { \
+        *fromP = from; \
+        return; \
+      } \
+      *(*toP)++ = ((lo >> 6) | (hi << 2) |  UTF8_cval2); \
+      *(*toP)++ = ((lo & 0x3f) | 0x80); \
+      break; \
+    default: \
+      if (toLim -  *toP < 3)  { \
+        *fromP = from; \
+        return; \
+      } \
+      /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
+      *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
+      *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
+      *(*toP)++ = ((lo & 0x3f) | 0x80); \
+      break; \
+    case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
+      if (toLim -  *toP < 4) { \
+        *fromP = from; \
+        return; \
+      } \
+      plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
+      *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
+      *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
+      from += 2; \
+      lo2 = GET_LO(from); \
+      *(*toP)++ = (((lo & 0x3) << 4) \
+                   | ((GET_HI(from) & 0x3) << 2) \
+                   | (lo2 >> 6) \
+                   | 0x80); \
+      *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
+      break; \
+    } \
+  } \
+  *fromP = from; \
+}
+
+#define DEFINE_UTF16_TO_UTF16(E) \
+static \
+void E ## toUtf16(const ENCODING *enc, \
+                  const char **fromP, const char *fromLim, \
+                  unsigned short **toP, const unsigned short *toLim) \
+{ \
+  itkExpatUnused(enc);\
+  /* Avoid copying first half only of surrogate */ \
+  if (fromLim - *fromP > ((toLim - *toP) << 1) \
+      && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
+    fromLim -= 2; \
+  for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
+    *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
+}
+
+#define SET2(ptr, ch) \
+  (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[0])
+#define GET_HI(ptr) ((unsigned char)(ptr)[1])
+
+DEFINE_UTF16_TO_UTF8(little2_)
+DEFINE_UTF16_TO_UTF16(little2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define SET2(ptr, ch) \
+  (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[1])
+#define GET_HI(ptr) ((unsigned char)(ptr)[0])
+
+DEFINE_UTF16_TO_UTF8(big2_)
+DEFINE_UTF16_TO_UTF16(big2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define LITTLE2_BYTE_TYPE(enc, p) \
+ ((p)[1] == 0 \
+  ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
+  : unicode_byte_type((p)[1], (p)[0]))
+#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
+#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
+#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \
+  UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
+#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+  UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
+
+#ifdef XML_MIN_SIZE
+
+static
+int little2_byteType(const ENCODING *enc, const char *p)
+{
+  return LITTLE2_BYTE_TYPE(enc, p);
+}
+
+static
+int little2_byteToAscii(const ENCODING *enc, const char *p)
+{
+  return LITTLE2_BYTE_TO_ASCII(enc, p);
+}
+
+static
+int little2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+  return LITTLE2_CHAR_MATCHES(enc, p, c);
+}
+
+static
+int little2_isNameMin(const ENCODING *enc, const char *p)
+{
+  return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static
+int little2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+  return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) little2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p) 
+#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding little2_encoding_ns = { 
+  { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 12
+    1
+#else
+    0
+#endif
+  },
+  {
+#include "asciitab.h"
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(little2_) EMPTY_VTABLE(little2_)
+};
+
+#endif
+
+static const struct normal_encoding little2_encoding = { 
+  { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 12
+    1
+#else
+    0
+#endif
+  },
+  {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(little2_) EMPTY_VTABLE(little2_)
+};
+
+#if XML_BYTE_ORDER != 21
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_little2_encoding_ns = { 
+  { VTABLE, 2, 0, 1 },
+  {
+#include "iasciitab.h"
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(little2_) EMPTY_VTABLE(little2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_little2_encoding = { 
+  { VTABLE, 2, 0, 1 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(little2_) EMPTY_VTABLE(little2_)
+};
+
+#endif
+
+
+#define BIG2_BYTE_TYPE(enc, p) \
+ ((p)[0] == 0 \
+  ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
+  : unicode_byte_type((p)[0], (p)[1]))
+#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
+#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
+#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \
+  UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
+#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+  UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
+
+#ifdef XML_MIN_SIZE
+
+static
+int big2_byteType(const ENCODING *enc, const char *p)
+{
+  return BIG2_BYTE_TYPE(enc, p);
+}
+
+static
+int big2_byteToAscii(const ENCODING *enc, const char *p)
+{
+  return BIG2_BYTE_TO_ASCII(enc, p);
+}
+
+static
+int big2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+  return BIG2_CHAR_MATCHES(enc, p, c);
+}
+
+static
+int big2_isNameMin(const ENCODING *enc, const char *p)
+{
+  return BIG2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static
+int big2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+  return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) big2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p) 
+#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding big2_encoding_ns = {
+  { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 21
+  1
+#else
+  0
+#endif
+  },
+  {
+#include "asciitab.h"
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(big2_) EMPTY_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding big2_encoding = {
+  { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 21
+  1
+#else
+  0
+#endif
+  },
+  {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(big2_) EMPTY_VTABLE(big2_)
+};
+
+#if XML_BYTE_ORDER != 12
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_big2_encoding_ns = {
+  { VTABLE, 2, 0, 1 },
+  {
+#include "iasciitab.h"
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(big2_) EMPTY_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_big2_encoding = {
+  { VTABLE, 2, 0, 1 },
+  {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+  },
+  STANDARD_VTABLE(big2_) EMPTY_VTABLE(big2_)
+};
+
+#endif
+
+#undef PREFIX
+
+static
+int streqci(const char *s1, const char *s2)
+{
+  for (;;) {
+    char c1 = *s1++;
+    char c2 = *s2++;
+    if (ASCII_a <= c1 && c1 <= ASCII_z)
+      c1 += ASCII_A - ASCII_a;
+    if (ASCII_a <= c2 && c2 <= ASCII_z)
+      c2 += ASCII_A - ASCII_a;
+    if (c1 != c2)
+      return 0;
+    if (!c1)
+      break;
+  }
+  return 1;
+}
+
+static
+void initUpdatePosition(const ENCODING *enc, const char *ptr,
+                        const char *end, POSITION *pos)
+{
+  itkExpatUnused(enc);
+  normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
+}
+
+static
+int toAscii(const ENCODING *enc, const char *ptr, const char *end)
+{
+  char buf[1];
+  char *p = buf;
+  XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
+  if (p == buf)
+    return -1;
+  else
+    return buf[0];
+}
+
+static
+int isSpace(int c)
+{
+  switch (c) {
+  case 0x20:
+  case 0xD:
+  case 0xA:
+  case 0x9:     
+    return 1;
+  }
+  return 0;
+}
+
+/* Return 1 if there's just optional white space
+or there's an S followed by name=val. */
+static
+int parsePseudoAttribute(const ENCODING *enc,
+                         const char *ptr,
+                         const char *end,
+                         const char **namePtr,
+                         const char **nameEndPtr,
+                         const char **valPtr,
+                         const char **nextTokPtr)
+{
+  int c;
+  char open;
+  if (ptr == end) {
+    *namePtr = 0;
+    return 1;
+  }
+  if (!isSpace(toAscii(enc, ptr, end))) {
+    *nextTokPtr = ptr;
+    return 0;
+  }
+  do {
+    ptr += enc->minBytesPerChar;
+  } while (isSpace(toAscii(enc, ptr, end)));
+  if (ptr == end) {
+    *namePtr = 0;
+    return 1;
+  }
+  *namePtr = ptr;
+  for (;;) {
+    c = toAscii(enc, ptr, end);
+    if (c == -1) {
+      *nextTokPtr = ptr;
+      return 0;
+    }
+    if (c == ASCII_EQUALS) {
+      *nameEndPtr = ptr;
+      break;
+    }
+    if (isSpace(c)) {
+      *nameEndPtr = ptr;
+      do {
+        ptr += enc->minBytesPerChar;
+      } while (isSpace(c = toAscii(enc, ptr, end)));
+      if (c != ASCII_EQUALS) {
+        *nextTokPtr = ptr;
+        return 0;
+      }
+      break;
+    }
+    ptr += enc->minBytesPerChar;
+  }
+  if (ptr == *namePtr) {
+    *nextTokPtr = ptr;
+    return 0;
+  }
+  ptr += enc->minBytesPerChar;
+  c = toAscii(enc, ptr, end);
+  while (isSpace(c)) {
+    ptr += enc->minBytesPerChar;
+    c = toAscii(enc, ptr, end);
+  }
+  if (c != ASCII_QUOT && c != ASCII_APOS) {
+    *nextTokPtr = ptr;
+    return 0;
+  }
+  open = c;
+  ptr += enc->minBytesPerChar;
+  *valPtr = ptr;
+  for (;; ptr += enc->minBytesPerChar) {
+    c = toAscii(enc, ptr, end);
+    if (c == open)
+      break;
+    if (!(ASCII_a <= c && c <= ASCII_z)
+        && !(ASCII_A <= c && c <= ASCII_Z)
+        && !(ASCII_0 <= c && c <= ASCII_9)
+        && c != ASCII_PERIOD
+        && c != ASCII_MINUS
+        && c != ASCII_UNDERSCORE) {
+      *nextTokPtr = ptr;
+      return 0;
+    }
+  }
+  *nextTokPtr = ptr + enc->minBytesPerChar;
+  return 1;
+}
+
+static const char KW_version[] = {
+  ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'
+};
+
+static const char KW_encoding[] = {
+  ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0'
+};
+
+static const char KW_standalone[] = {
+  ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0'
+};
+
+static const char KW_yes[] = {
+  ASCII_y, ASCII_e, ASCII_s,  '\0'
+};
+
+static const char KW_no[] = {
+  ASCII_n, ASCII_o,  '\0'
+};
+
+static
+int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *,
+                                                     const char *,
+                                                     const char *),
+                   int isGeneralTextEntity,
+                   const ENCODING *enc,
+                   const char *ptr,
+                   const char *end,
+                   const char **badPtr,
+                   const char **versionPtr,
+                   const char **versionEndPtr,
+                   const char **encodingName,
+                   const ENCODING **encoding,
+                   int *standalone)
+{
+  const char *val = 0;
+  const char *name = 0;
+  const char *nameEnd = 0;
+  ptr += 5 * enc->minBytesPerChar;
+  end -= 2 * enc->minBytesPerChar;
+  if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) || !name) {
+    *badPtr = ptr;
+    return 0;
+  }
+  if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
+    if (!isGeneralTextEntity) {
+      *badPtr = name;
+      return 0;
+    }
+  }
+  else {
+    if (versionPtr)
+      *versionPtr = val;
+    if (versionEndPtr)
+      *versionEndPtr = ptr;
+    if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+      *badPtr = ptr;
+      return 0;
+    }
+    if (!name) {
+      if (isGeneralTextEntity) {
+        /* a TextDecl must have an EncodingDecl */
+        *badPtr = ptr;
+        return 0;
+      }
+      return 1;
+    }
+  }
+  if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
+    int c = toAscii(enc, val, end);
+    if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) {
+      *badPtr = val;
+      return 0;
+    }
+    if (encodingName)
+      *encodingName = val;
+    if (encoding)
+      *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
+    if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+      *badPtr = ptr;
+      return 0;
+    }
+    if (!name)
+      return 1;
+  }
+  if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) || isGeneralTextEntity) {
+    *badPtr = name;
+    return 0;
+  }
+  if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
+    if (standalone)
+      *standalone = 1;
+  }
+  else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
+    if (standalone)
+      *standalone = 0;
+  }
+  else {
+    *badPtr = val;
+    return 0;
+  }
+  while (isSpace(toAscii(enc, ptr, end)))
+    ptr += enc->minBytesPerChar;
+  if (ptr != end) {
+    *badPtr = ptr;
+    return 0;
+  }
+  return 1;
+}
+
+static
+int checkCharRefNumber(int result)
+{
+  switch (result >> 8) {
+  case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+  case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+    return -1;
+  case 0:
+    if (latin1_encoding.type[result] == BT_NONXML)
+      return -1;
+    break;
+  case 0xFF:
+    if (result == 0xFFFE || result == 0xFFFF)
+      return -1;
+    break;
+  }
+  return result;
+}
+
+int XmlUtf8Encode(int c, char *buf)
+{
+  enum {
+    /* minN is minimum legal resulting value for N byte sequence */
+    min2 = 0x80,
+    min3 = 0x800,
+    min4 = 0x10000
+  };
+
+  if (c < 0)
+    return 0;
+  if (c < min2) {
+    buf[0] = (c | UTF8_cval1);
+    return 1;
+  }
+  if (c < min3) {
+    buf[0] = ((c >> 6) | UTF8_cval2);
+    buf[1] = ((c & 0x3f) | 0x80);
+    return 2;
+  }
+  if (c < min4) {
+    buf[0] = ((c >> 12) | UTF8_cval3);
+    buf[1] = (((c >> 6) & 0x3f) | 0x80);
+    buf[2] = ((c & 0x3f) | 0x80);
+    return 3;
+  }
+  if (c < 0x110000) {
+    buf[0] = ((c >> 18) | UTF8_cval4);
+    buf[1] = (((c >> 12) & 0x3f) | 0x80);
+    buf[2] = (((c >> 6) & 0x3f) | 0x80);
+    buf[3] = ((c & 0x3f) | 0x80);
+    return 4;
+  }
+  return 0;
+}
+
+int XmlUtf16Encode(int charNum, unsigned short *buf)
+{
+  if (charNum < 0)
+    return 0;
+  if (charNum < 0x10000) {
+    buf[0] = charNum;
+    return 1;
+  }
+  if (charNum < 0x110000) {
+    charNum -= 0x10000;
+    buf[0] = (charNum >> 10) + 0xD800;
+    buf[1] = (charNum & 0x3FF) + 0xDC00;
+    return 2;
+  }
+  return 0;
+}
+
+struct unknown_encoding {
+  struct normal_encoding normal;
+  int (*convert)(void *userData, const char *p);
+  void *userData;
+  unsigned short utf16[256];
+  char utf8[256][4];
+};
+
+int XmlSizeOfUnknownEncoding(void)
+{
+  return sizeof(struct unknown_encoding);
+}
+
+static
+int unknown_isName(const ENCODING *enc, const char *p)
+{
+  int c = ((const struct unknown_encoding *)enc)
+          ->convert(((const struct unknown_encoding *)enc)->userData, p);
+  if (c & ~0xFFFF)
+    return 0;
+  return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
+}
+
+static
+int unknown_isNmstrt(const ENCODING *enc, const char *p)
+{
+  int c = ((const struct unknown_encoding *)enc)
+          ->convert(((const struct unknown_encoding *)enc)->userData, p);
+  if (c & ~0xFFFF)
+    return 0;
+  return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
+}
+
+static
+int unknown_isInvalid(const ENCODING *enc, const char *p)
+{
+  int c = ((const struct unknown_encoding *)enc)
+           ->convert(((const struct unknown_encoding *)enc)->userData, p);
+  return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
+}
+
+static
+void unknown_toUtf8(const ENCODING *enc,
+                    const char **fromP, const char *fromLim,
+                    char **toP, const char *toLim)
+{
+  char buf[XML_UTF8_ENCODE_MAX];
+  for (;;) {
+    const char *utf8;
+    int n;
+    if (*fromP == fromLim)
+      break;
+    utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP];
+    n = *utf8++;
+    if (n == 0) {
+      int c = ((const struct unknown_encoding *)enc)
+              ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
+      n = XmlUtf8Encode(c, buf);
+      if (n > toLim - *toP)
+        break;
+      utf8 = buf;
+      *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
+                 - (BT_LEAD2 - 2);
+    }
+    else {
+      if (n > toLim - *toP)
+        break;
+      (*fromP)++;
+    }
+    do {
+      *(*toP)++ = *utf8++;
+    } while (--n != 0);
+  }
+}
+
+static
+void unknown_toUtf16(const ENCODING *enc,
+                     const char **fromP, const char *fromLim,
+                     unsigned short **toP, const unsigned short *toLim)
+{
+  while (*fromP != fromLim && *toP != toLim) {
+    unsigned short c
+      = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP];
+    if (c == 0) {
+      c = (unsigned short)((const struct unknown_encoding *)enc)
+           ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
+      *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
+                 - (BT_LEAD2 - 2);
+    }
+    else
+      (*fromP)++;
+    *(*toP)++ = c;
+  }
+}
+
+ENCODING *
+XmlInitUnknownEncoding(void *mem,
+                       int *table,
+                       int (*convert)(void *userData, const char *p),
+                       void *userData)
+{
+  int i;
+  struct unknown_encoding *e = mem;
+  for (i = 0; i < (int)sizeof(struct normal_encoding); i++)
+    ((char *)mem)[i] = ((char *)&latin1_encoding)[i];
+  for (i = 0; i < 128; i++)
+    if (latin1_encoding.type[i] != BT_OTHER
+        && latin1_encoding.type[i] != BT_NONXML
+        && table[i] != i)
+      return 0;
+  for (i = 0; i < 256; i++) {
+    int c = table[i];
+    if (c == -1) {
+      e->normal.type[i] = BT_MALFORM;
+      /* This shouldn't really get used. */
+      e->utf16[i] = 0xFFFF;
+      e->utf8[i][0] = 1;
+      e->utf8[i][1] = 0;
+    }
+    else if (c < 0) {
+      if (c < -4)
+        return 0;
+      e->normal.type[i] = BT_LEAD2 - (c + 2);
+      e->utf8[i][0] = 0;
+      e->utf16[i] = 0;
+    }
+    else if (c < 0x80) {
+      if (latin1_encoding.type[c] != BT_OTHER
+          && latin1_encoding.type[c] != BT_NONXML
+          && c != i)
+        return 0;
+      e->normal.type[i] = latin1_encoding.type[c];
+      e->utf8[i][0] = 1;
+      e->utf8[i][1] = (char)c;
+      e->utf16[i] = c == 0 ? 0xFFFF : c;
+    }
+    else if (checkCharRefNumber(c) < 0) {
+      e->normal.type[i] = BT_NONXML;
+      /* This shouldn't really get used. */
+      e->utf16[i] = 0xFFFF;
+      e->utf8[i][0] = 1;
+      e->utf8[i][1] = 0;
+    }
+    else {
+      if (c > 0xFFFF)
+        return 0;
+      if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
+        e->normal.type[i] = BT_NMSTRT;
+      else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
+        e->normal.type[i] = BT_NAME;
+      else
+        e->normal.type[i] = BT_OTHER;
+      e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
+      e->utf16[i] = c;
+    }
+  }
+  e->userData = userData;
+  e->convert = convert;
+  if (convert) {
+    e->normal.isName2 = unknown_isName;
+    e->normal.isName3 = unknown_isName;
+    e->normal.isName4 = unknown_isName;
+    e->normal.isNmstrt2 = unknown_isNmstrt;
+    e->normal.isNmstrt3 = unknown_isNmstrt;
+    e->normal.isNmstrt4 = unknown_isNmstrt;
+    e->normal.isInvalid2 = unknown_isInvalid;
+    e->normal.isInvalid3 = unknown_isInvalid;
+    e->normal.isInvalid4 = unknown_isInvalid;
+  }
+  e->normal.enc.utf8Convert = unknown_toUtf8;
+  e->normal.enc.utf16Convert = unknown_toUtf16;
+  return &(e->normal.enc);
+}
+
+/* If this enumeration is changed, getEncodingIndex and encodings
+must also be changed. */
+enum {
+  UNKNOWN_ENC = -1,
+  ISO_8859_1_ENC = 0,
+  US_ASCII_ENC,
+  UTF_8_ENC,
+  UTF_16_ENC,
+  UTF_16BE_ENC,
+  UTF_16LE_ENC,
+  /* must match encodingNames up to here */
+  NO_ENC
+};
+
+static const char KW_ISO_8859_1[] = {
+  ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1, '\0'
+};
+static const char KW_US_ASCII[] = {
+  ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, '\0'
+};
+static const char KW_UTF_8[] =  {
+  ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'
+};
+static const char KW_UTF_16[] = {
+  ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'
+};
+static const char KW_UTF_16BE[] = {
+  ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, '\0'
+};
+static const char KW_UTF_16LE[] = {
+  ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, '\0'
+};
+
+static
+int getEncodingIndex(const char *name)
+{
+  static const char *encodingNames[] = {
+    KW_ISO_8859_1,
+    KW_US_ASCII,
+    KW_UTF_8,
+    KW_UTF_16,
+    KW_UTF_16BE,
+    KW_UTF_16LE,
+  };
+  int i;
+  if (name == 0)
+    return NO_ENC;
+  for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++)
+    if (streqci(name, encodingNames[i]))
+      return i;
+  return UNKNOWN_ENC;
+}
+
+/* For binary compatibility, we store the index of the encoding specified
+at initialization in the isUtf16 member. */
+
+#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
+#define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i)
+
+/* This is what detects the encoding.
+encodingTable maps from encoding indices to encodings;
+INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding;
+state is XML_CONTENT_STATE if we're parsing an external text entity,
+and XML_PROLOG_STATE otherwise.
+*/
+
+
+static
+int initScan(const ENCODING **encodingTable,
+             const INIT_ENCODING *enc,
+             int state,
+             const char *ptr,
+             const char *end,
+             const char **nextTokPtr)
+{
+  const ENCODING **encPtr;
+
+  if (ptr == end)
+    return XML_TOK_NONE;
+  encPtr = enc->encPtr;
+  if (ptr + 1 == end) {
+    /* only a single byte available for auto-detection */
+#ifndef XML_DTD /* FIXME */
+    /* a well-formed document entity must have more than one byte */
+    if (state != XML_CONTENT_STATE)
+      return XML_TOK_PARTIAL;
+#endif
+    /* so we're parsing an external text entity... */
+    /* if UTF-16 was externally specified, then we need at least 2 bytes */
+    switch (INIT_ENC_INDEX(enc)) {
+    case UTF_16_ENC:
+    case UTF_16LE_ENC:
+    case UTF_16BE_ENC:
+      return XML_TOK_PARTIAL;
+    }
+    switch ((unsigned char)*ptr) {
+    case 0xFE:
+    case 0xFF:
+    case 0xEF: /* possibly first byte of UTF-8 BOM */
+      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+          && state == XML_CONTENT_STATE)
+        break;
+      /* fall through */
+    case 0x00:
+    case 0x3C:
+      return XML_TOK_PARTIAL;
+    }
+  }
+  else {
+    switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
+    case 0xFEFF:
+      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+          && state == XML_CONTENT_STATE)
+        break;
+      *nextTokPtr = ptr + 2;
+      *encPtr = encodingTable[UTF_16BE_ENC];
+      return XML_TOK_BOM;
+    /* 00 3C is handled in the default case */
+    case 0x3C00:
+      if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
+           || INIT_ENC_INDEX(enc) == UTF_16_ENC)
+          && state == XML_CONTENT_STATE)
+        break;
+      *encPtr = encodingTable[UTF_16LE_ENC];
+      return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+    case 0xFFFE:
+      if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+          && state == XML_CONTENT_STATE)
+        break;
+      *nextTokPtr = ptr + 2;
+      *encPtr = encodingTable[UTF_16LE_ENC];
+      return XML_TOK_BOM;
+    case 0xEFBB:
+      /* Maybe a UTF-8 BOM (EF BB BF) */
+      /* If there's an explicitly specified (external) encoding
+         of ISO-8859-1 or some flavour of UTF-16
+         and this is an external text entity,
+         don't look for the BOM,
+         because it might be a legal data. */
+      if (state == XML_CONTENT_STATE) {
+        int e = INIT_ENC_INDEX(enc);
+        if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC)
+          break;
+      }
+      if (ptr + 2 == end)
+        return XML_TOK_PARTIAL;
+      if ((unsigned char)ptr[2] == 0xBF) {
+        *nextTokPtr = ptr + 3;
+        *encPtr = encodingTable[UTF_8_ENC];
+        return XML_TOK_BOM;
+      }
+      break;
+    default:
+      if (ptr[0] == '\0') {
+        /* 0 isn't a legal data character. Furthermore a document entity can only
+           start with ASCII characters.  So the only way this can fail to be big-endian
+           UTF-16 if it it's an external parsed general entity that's labelled as
+           UTF-16LE. */
+        if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
+          break;
+        *encPtr = encodingTable[UTF_16BE_ENC];
+        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+      }
+      else if (ptr[1] == '\0') {
+        /* We could recover here in the case:
+            - parsing an external entity
+            - second byte is 0
+            - no externally specified encoding
+            - no encoding declaration
+           by assuming UTF-16LE.  But we don't, because this would mean when
+           presented just with a single byte, we couldn't reliably determine
+           whether we needed further bytes. */
+        if (state == XML_CONTENT_STATE)
+          break;
+        *encPtr = encodingTable[UTF_16LE_ENC];
+        return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+      }
+      break;
+    }
+  }
+  *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
+  return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+}
+
+
+#define NS(x) x
+#define ns(x) x
+#include "xmltok_ns.c"
+#undef NS
+#undef ns
+
+#ifdef XML_NS
+
+#define NS(x) x ## NS
+#define ns(x) x ## _ns
+
+#include "xmltok_ns.c"
+
+#undef NS
+#undef ns
+
+ENCODING *
+XmlInitUnknownEncodingNS(void *mem,
+                         int *table,
+                         int (*convert)(void *userData, const char *p),
+                         void *userData)
+{
+  ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
+  if (enc)
+    ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
+  return enc;
+}
+
+#endif /* XML_NS */
diff --git a/Utilities/ITK/Utilities/expat/xmltok.h b/Utilities/ITK/Utilities/expat/xmltok.h
new file mode 100644
index 0000000000000000000000000000000000000000..cdf49b2cba6ff80488d00e045d7925f4698a2f6c
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/xmltok.h
@@ -0,0 +1,299 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#ifndef XmlTok_INCLUDED
+#define XmlTok_INCLUDED 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The following token may be returned by XmlContentTok */
+#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of
+                                    illegal ]]> sequence */
+/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
+#define XML_TOK_NONE -4    /* The string to be scanned is empty */
+#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
+                                  might be part of CRLF sequence */ 
+#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
+#define XML_TOK_PARTIAL -1 /* only part of a token */
+#define XML_TOK_INVALID 0
+
+/* The following tokens are returned by XmlContentTok; some are also
+  returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */
+
+#define XML_TOK_START_TAG_WITH_ATTS 1
+#define XML_TOK_START_TAG_NO_ATTS 2
+#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
+#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
+#define XML_TOK_END_TAG 5
+#define XML_TOK_DATA_CHARS 6
+#define XML_TOK_DATA_NEWLINE 7
+#define XML_TOK_CDATA_SECT_OPEN 8
+#define XML_TOK_ENTITY_REF 9
+#define XML_TOK_CHAR_REF 10     /* numeric character reference */
+
+/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
+#define XML_TOK_PI 11      /* processing instruction */
+#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
+#define XML_TOK_COMMENT 13
+#define XML_TOK_BOM 14     /* Byte order mark */
+
+/* The following tokens are returned only by XmlPrologTok */
+#define XML_TOK_PROLOG_S 15
+#define XML_TOK_DECL_OPEN 16 /* <!foo */
+#define XML_TOK_DECL_CLOSE 17 /* > */
+#define XML_TOK_NAME 18
+#define XML_TOK_NMTOKEN 19
+#define XML_TOK_POUND_NAME 20 /* #name */
+#define XML_TOK_OR 21 /* | */
+#define XML_TOK_PERCENT 22
+#define XML_TOK_OPEN_PAREN 23
+#define XML_TOK_CLOSE_PAREN 24
+#define XML_TOK_OPEN_BRACKET 25
+#define XML_TOK_CLOSE_BRACKET 26
+#define XML_TOK_LITERAL 27
+#define XML_TOK_PARAM_ENTITY_REF 28
+#define XML_TOK_INSTANCE_START 29
+
+/* The following occur only in element type declarations */
+#define XML_TOK_NAME_QUESTION 30 /* name? */
+#define XML_TOK_NAME_ASTERISK 31 /* name* */
+#define XML_TOK_NAME_PLUS 32 /* name+ */
+#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
+#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
+#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
+#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
+#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
+#define XML_TOK_COMMA 38
+
+/* The following token is returned only by XmlAttributeValueTok */
+#define XML_TOK_ATTRIBUTE_VALUE_S 39
+
+/* The following token is returned only by XmlCdataSectionTok */
+#define XML_TOK_CDATA_SECT_CLOSE 40
+
+/* With namespace processing this is returned by XmlPrologTok
+   for a name with a colon. */
+#define XML_TOK_PREFIXED_NAME 41
+
+#ifdef XML_DTD
+#define XML_TOK_IGNORE_SECT 42
+#endif /* XML_DTD */
+
+#ifdef XML_DTD
+#define XML_N_STATES 4
+#else /* not XML_DTD */
+#define XML_N_STATES 3
+#endif /* not XML_DTD */
+
+#define XML_PROLOG_STATE 0
+#define XML_CONTENT_STATE 1
+#define XML_CDATA_SECTION_STATE 2
+#ifdef XML_DTD
+#define XML_IGNORE_SECTION_STATE 3
+#endif /* XML_DTD */
+
+#define XML_N_LITERAL_TYPES 2
+#define XML_ATTRIBUTE_VALUE_LITERAL 0
+#define XML_ENTITY_VALUE_LITERAL 1
+
+/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
+#define XML_UTF8_ENCODE_MAX 4
+/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
+#define XML_UTF16_ENCODE_MAX 2
+
+typedef struct position {
+  /* first line and first column are 0 not 1 */
+  unsigned long lineNumber;
+  unsigned long columnNumber;
+} POSITION;
+
+typedef struct {
+  const char *name;
+  const char *valuePtr;
+  const char *valueEnd;
+  char normalized;
+} ATTRIBUTE;
+
+struct encoding;
+typedef struct encoding ENCODING;
+
+struct encoding {
+  int (*scanners[XML_N_STATES])(const ENCODING *,
+                                const char *,
+                                const char *,
+                                const char **);
+  int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *,
+                                              const char *,
+                                              const char *,
+                                              const char **);
+  int (*sameName)(const ENCODING *,
+                  const char *, const char *);
+  int (*nameMatchesAscii)(const ENCODING *,
+                          const char *, const char *, const char *);
+  int (*nameLength)(const ENCODING *, const char *);
+  const char *(*skipS)(const ENCODING *, const char *);
+  int (*getAtts)(const ENCODING *enc, const char *ptr,
+                 int attsMax, ATTRIBUTE *atts);
+  int (*charRefNumber)(const ENCODING *enc, const char *ptr);
+  int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
+  void (*updatePosition)(const ENCODING *,
+                         const char *ptr,
+                         const char *end,
+                         POSITION *);
+  int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+                    const char **badPtr);
+  void (*utf8Convert)(const ENCODING *enc,
+                      const char **fromP,
+                      const char *fromLim,
+                      char **toP,
+                      const char *toLim);
+  void (*utf16Convert)(const ENCODING *enc,
+                       const char **fromP,
+                       const char *fromLim,
+                       unsigned short **toP,
+                       const unsigned short *toLim);
+  int minBytesPerChar;
+  char isUtf8;
+  char isUtf16;
+};
+
+/*
+Scan the string starting at ptr until the end of the next complete token,
+but do not scan past eptr.  Return an integer giving the type of token.
+
+Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
+
+Return XML_TOK_PARTIAL when the string does not contain a complete token;
+nextTokPtr will not be set.
+
+Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr
+will be set to point to the character which made the token invalid.
+
+Otherwise the string starts with a valid token; nextTokPtr will be set to point
+to the character following the end of that token.
+
+Each data character counts as a single token, but adjacent data characters
+may be returned together.  Similarly for characters in the prolog outside
+literals, comments and processing instructions.
+*/
+
+
+#define XmlTok(enc, state, ptr, end, nextTokPtr) \
+  (((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
+
+#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
+   XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
+
+#define XmlContentTok(enc, ptr, end, nextTokPtr) \
+   XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
+
+#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
+   XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
+
+#ifdef XML_DTD
+
+#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
+   XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
+
+#endif /* XML_DTD */
+
+/* This is used for performing a 2nd-level tokenization on
+the content of a literal that has already been returned by XmlTok. */ 
+
+#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
+  (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
+
+#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
+   XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
+   XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2))
+
+#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
+  (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
+
+#define XmlNameLength(enc, ptr) \
+  (((enc)->nameLength)(enc, ptr))
+
+#define XmlSkipS(enc, ptr) \
+  (((enc)->skipS)(enc, ptr))
+
+#define XmlGetAttributes(enc, ptr, attsMax, atts) \
+  (((enc)->getAtts)(enc, ptr, attsMax, atts))
+
+#define XmlCharRefNumber(enc, ptr) \
+  (((enc)->charRefNumber)(enc, ptr))
+
+#define XmlPredefinedEntityName(enc, ptr, end) \
+  (((enc)->predefinedEntityName)(enc, ptr, end))
+
+#define XmlUpdatePosition(enc, ptr, end, pos) \
+  (((enc)->updatePosition)(enc, ptr, end, pos))
+
+#define XmlIsPublicId(enc, ptr, end, badPtr) \
+  (((enc)->isPublicId)(enc, ptr, end, badPtr))
+
+#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
+  (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
+
+#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
+  (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
+
+typedef struct {
+  ENCODING initEnc;
+  const ENCODING **encPtr;
+} INIT_ENCODING;
+
+int  XmlParseXmlDecl(int isGeneralTextEntity,
+                              const ENCODING *enc,
+                              const char *ptr,
+                              const char *end,
+                              const char **badPtr,
+                              const char **versionPtr,
+                              const char **versionEndPtr,
+                              const char **encodingNamePtr,
+                              const ENCODING **namedEncodingPtr,
+                              int *standalonePtr);
+
+int  XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING  *XmlGetUtf8InternalEncoding(void);
+const ENCODING  *XmlGetUtf16InternalEncoding(void);
+int  XmlUtf8Encode(int charNumber, char *buf);
+int  XmlUtf16Encode(int charNumber, unsigned short *buf);
+
+int  XmlSizeOfUnknownEncoding(void);
+ENCODING  *
+XmlInitUnknownEncoding(void *mem,
+                       int *table,
+                       int (*conv)(void *userData, const char *p),
+                       void *userData);
+
+int  XmlParseXmlDeclNS(int isGeneralTextEntity,
+                                const ENCODING *enc,
+                                const char *ptr,
+                                const char *end,
+                                const char **badPtr,
+                                const char **versionPtr,
+                                const char **versionEndPtr,
+                                const char **encodingNamePtr,
+                                const ENCODING **namedEncodingPtr,
+                                int *standalonePtr);
+int  XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING  *XmlGetUtf8InternalEncodingNS(void);
+const ENCODING  *XmlGetUtf16InternalEncodingNS(void);
+ENCODING  *
+XmlInitUnknownEncodingNS(void *mem,
+                         int *table,
+                         int (*conv)(void *userData, const char *p),
+                         void *userData);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlTok_INCLUDED */
diff --git a/Utilities/ITK/Utilities/expat/xmltok_impl.c b/Utilities/ITK/Utilities/expat/xmltok_impl.c
new file mode 100644
index 0000000000000000000000000000000000000000..652ce1bd825db6bd26c02ee05ab23ab42f490e41
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/xmltok_impl.c
@@ -0,0 +1,1773 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#ifndef IS_INVALID_CHAR
+#define IS_INVALID_CHAR(enc, ptr, n) (0)
+#endif
+
+#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
+    case BT_LEAD ## n: \
+      if (end - ptr < n) \
+        return XML_TOK_PARTIAL_CHAR; \
+      if (IS_INVALID_CHAR(enc, ptr, n)) { \
+        *(nextTokPtr) = (ptr); \
+        return XML_TOK_INVALID; \
+      } \
+      ptr += n; \
+      break;
+
+#define INVALID_CASES(ptr, nextTokPtr) \
+  INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
+  INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
+  INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
+  case BT_NONXML: \
+  case BT_MALFORM: \
+  case BT_TRAIL: \
+    *(nextTokPtr) = (ptr); \
+    return XML_TOK_INVALID;
+
+#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
+   case BT_LEAD ## n: \
+     if (end - ptr < n) \
+       return XML_TOK_PARTIAL_CHAR; \
+     if (!IS_NAME_CHAR(enc, ptr, n)) { \
+       *nextTokPtr = ptr; \
+       return XML_TOK_INVALID; \
+     } \
+     ptr += n; \
+     break;
+
+#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
+  case BT_NONASCII: \
+    if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
+      *nextTokPtr = ptr; \
+      return XML_TOK_INVALID; \
+    } \
+  case BT_NMSTRT: \
+  case BT_HEX: \
+  case BT_DIGIT: \
+  case BT_NAME: \
+  case BT_MINUS: \
+    ptr += MINBPC(enc); \
+    break; \
+  CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
+  CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
+  CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
+
+#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
+   case BT_LEAD ## n: \
+     if (end - ptr < n) \
+       return XML_TOK_PARTIAL_CHAR; \
+     if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
+       *nextTokPtr = ptr; \
+       return XML_TOK_INVALID; \
+     } \
+     ptr += n; \
+     break;
+
+#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
+  case BT_NONASCII: \
+    if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
+      *nextTokPtr = ptr; \
+      return XML_TOK_INVALID; \
+    } \
+  case BT_NMSTRT: \
+  case BT_HEX: \
+    ptr += MINBPC(enc); \
+    break; \
+  CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
+  CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
+  CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
+
+#ifndef PREFIX
+#define PREFIX(ident) ident
+#endif
+
+/* ptr points to character following "<!-" */
+
+static
+int PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end,
+                        const char **nextTokPtr)
+{
+  if (ptr != end) {
+    if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+    ptr += MINBPC(enc);
+    while (ptr != end) {
+      switch (BYTE_TYPE(enc, ptr)) {
+      INVALID_CASES(ptr, nextTokPtr)
+      case BT_MINUS:
+        if ((ptr += MINBPC(enc)) == end)
+          return XML_TOK_PARTIAL;
+        if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+          if ((ptr += MINBPC(enc)) == end)
+            return XML_TOK_PARTIAL;
+          if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+            *nextTokPtr = ptr;
+            return XML_TOK_INVALID;
+          }
+          *nextTokPtr = ptr + MINBPC(enc);
+          return XML_TOK_COMMENT;
+        }
+        break;
+      default:
+        ptr += MINBPC(enc);
+        break;
+      }
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<!" */
+
+static
+int PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end,
+                     const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  case BT_MINUS:
+    return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_LSQB:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_COND_SECT_OPEN;
+  case BT_NMSTRT:
+  case BT_HEX:
+    ptr += MINBPC(enc);
+    break;
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_PERCNT:
+      if (ptr + MINBPC(enc) == end)
+        return XML_TOK_PARTIAL;
+      /* don't allow <!ENTITY% foo "whatever"> */
+      switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
+      case BT_S: case BT_CR: case BT_LF: case BT_PERCNT:
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      /* fall through */
+    case BT_S: case BT_CR: case BT_LF:
+      *nextTokPtr = ptr;
+      return XML_TOK_DECL_OPEN;
+    case BT_NMSTRT:
+    case BT_HEX:
+      ptr += MINBPC(enc);
+      break;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr)
+{
+  int upper = 0;
+  itkExpatUnused(enc);
+  *tokPtr = XML_TOK_PI;
+  if (end - ptr != MINBPC(enc)*3)
+    return 1;
+  switch (BYTE_TO_ASCII(enc, ptr)) {
+  case ASCII_x:
+    break;
+  case ASCII_X:
+    upper = 1;
+    break;
+  default:
+    return 1;
+  }
+  ptr += MINBPC(enc);
+  switch (BYTE_TO_ASCII(enc, ptr)) {
+  case ASCII_m:
+    break;
+  case ASCII_M:
+    upper = 1;
+    break;
+  default:
+    return 1;
+  }
+  ptr += MINBPC(enc);
+  switch (BYTE_TO_ASCII(enc, ptr)) {
+  case ASCII_l:
+    break;
+  case ASCII_L:
+    upper = 1;
+    break;
+  default:
+    return 1;
+  }
+  if (upper)
+    return 0;
+  *tokPtr = XML_TOK_XML_DECL;
+  return 1;
+}
+
+/* ptr points to character following "<?" */
+
+static
+int PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end,
+                   const char **nextTokPtr)
+{
+  int tok;
+  const char *target = ptr;
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_S: case BT_CR: case BT_LF:
+      if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      ptr += MINBPC(enc);
+      while (ptr != end) {
+        switch (BYTE_TYPE(enc, ptr)) {
+        INVALID_CASES(ptr, nextTokPtr)
+        case BT_QUEST:
+          ptr += MINBPC(enc);
+          if (ptr == end)
+            return XML_TOK_PARTIAL;
+          if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+            *nextTokPtr = ptr + MINBPC(enc);
+            return tok;
+          }
+          break;
+        default:
+          ptr += MINBPC(enc);
+          break;
+        }
+      }
+      return XML_TOK_PARTIAL;
+    case BT_QUEST:
+      if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      ptr += MINBPC(enc);
+      if (ptr == end)
+        return XML_TOK_PARTIAL;
+      if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+        *nextTokPtr = ptr + MINBPC(enc);
+        return tok;
+      }
+      /* fall through */
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+
+static
+int PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end,
+                             const char **nextTokPtr)
+{
+  static const char CDATA_LSQB[] = { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, ASCII_LSQB };
+  int i;
+  itkExpatUnused(enc);
+  /* CDATA[ */
+  if (end - ptr < 6 * MINBPC(enc))
+    return XML_TOK_PARTIAL;
+  for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
+    if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) {
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  *nextTokPtr = ptr;
+  return XML_TOK_CDATA_SECT_OPEN;
+}
+
+static
+int PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
+                            const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_NONE;
+  if (MINBPC(enc) > 1) {
+    size_t n = end - ptr;
+    if (n & (MINBPC(enc) - 1)) {
+      n &= ~(MINBPC(enc) - 1);
+      if (n == 0)
+        return XML_TOK_PARTIAL;
+      end = ptr + n;
+    }
+  }
+  switch (BYTE_TYPE(enc, ptr)) {
+  case BT_RSQB:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_PARTIAL;
+    if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+      break;
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_PARTIAL;
+    if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+      ptr -= MINBPC(enc);
+      break;
+    }
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_CDATA_SECT_CLOSE;
+  case BT_CR:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_PARTIAL;
+    if (BYTE_TYPE(enc, ptr) == BT_LF)
+      ptr += MINBPC(enc);
+    *nextTokPtr = ptr;
+    return XML_TOK_DATA_NEWLINE;
+  case BT_LF:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_DATA_NEWLINE;
+  INVALID_CASES(ptr, nextTokPtr)
+  default:
+    ptr += MINBPC(enc);
+    break;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: \
+      if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+        *nextTokPtr = ptr; \
+        return XML_TOK_DATA_CHARS; \
+      } \
+      ptr += n; \
+      break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_NONXML:
+    case BT_MALFORM:
+    case BT_TRAIL:
+    case BT_CR:
+    case BT_LF:
+    case BT_RSQB:
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  *nextTokPtr = ptr;
+  return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "</" */
+
+static
+int PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end,
+                       const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_S: case BT_CR: case BT_LF:
+      for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+        switch (BYTE_TYPE(enc, ptr)) {
+        case BT_S: case BT_CR: case BT_LF:
+          break;
+        case BT_GT:
+          *nextTokPtr = ptr + MINBPC(enc);
+          return XML_TOK_END_TAG;
+        default:
+          *nextTokPtr = ptr;
+          return XML_TOK_INVALID;
+        }
+      }
+      return XML_TOK_PARTIAL;
+#ifdef XML_NS
+    case BT_COLON:
+      /* no need to check qname syntax here, since end-tag must match exactly */
+      ptr += MINBPC(enc);
+      break;
+#endif
+    case BT_GT:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_END_TAG;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#X" */
+
+static
+int PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+                           const char **nextTokPtr)
+{
+  if (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_DIGIT:
+    case BT_HEX:
+      break;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+    for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+      switch (BYTE_TYPE(enc, ptr)) {
+      case BT_DIGIT:
+      case BT_HEX:
+        break;
+      case BT_SEMI:
+        *nextTokPtr = ptr + MINBPC(enc);
+        return XML_TOK_CHAR_REF;
+      default:
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#" */
+
+static
+int PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+                        const char **nextTokPtr)
+{
+  if (ptr != end) {
+    if (CHAR_MATCHES(enc, ptr, ASCII_x))
+      return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_DIGIT:
+      break;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+    for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+      switch (BYTE_TYPE(enc, ptr)) {
+      case BT_DIGIT:
+        break;
+      case BT_SEMI:
+        *nextTokPtr = ptr + MINBPC(enc);
+        return XML_TOK_CHAR_REF;
+      default:
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&" */
+
+static
+int PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
+                    const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  case BT_NUM:
+    return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_SEMI:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_ENTITY_REF;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following first character of attribute name */
+
+static
+int PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
+                     const char **nextTokPtr)
+{
+#ifdef XML_NS
+  int hadColon = 0;
+#endif
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+    case BT_COLON:
+      if (hadColon) {
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      hadColon = 1;
+      ptr += MINBPC(enc);
+      if (ptr == end)
+        return XML_TOK_PARTIAL;
+      switch (BYTE_TYPE(enc, ptr)) {
+      CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+      default:
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      break;
+#endif
+    case BT_S: case BT_CR: case BT_LF:
+      for (;;) {
+        int t;
+
+        ptr += MINBPC(enc);
+        if (ptr == end)
+          return XML_TOK_PARTIAL;
+        t = BYTE_TYPE(enc, ptr);
+        if (t == BT_EQUALS)
+          break;
+        switch (t) {
+        case BT_S:
+        case BT_LF:
+        case BT_CR:
+          break;
+        default:
+          *nextTokPtr = ptr;
+          return XML_TOK_INVALID;
+        }
+      }
+    /* fall through */
+    case BT_EQUALS:
+      {
+        int open;
+#ifdef XML_NS
+        hadColon = 0;
+#endif
+        for (;;) {
+          
+          ptr += MINBPC(enc);
+          if (ptr == end)
+            return XML_TOK_PARTIAL;
+          open = BYTE_TYPE(enc, ptr);
+          if (open == BT_QUOT || open == BT_APOS)
+            break;
+          switch (open) {
+          case BT_S:
+          case BT_LF:
+          case BT_CR:
+            break;
+          default:
+            *nextTokPtr = ptr;
+            return XML_TOK_INVALID;
+          }
+        }
+        ptr += MINBPC(enc);
+        /* in attribute value */
+        for (;;) {
+          int t;
+          if (ptr == end)
+            return XML_TOK_PARTIAL;
+          t = BYTE_TYPE(enc, ptr);
+          if (t == open)
+            break;
+          switch (t) {
+          INVALID_CASES(ptr, nextTokPtr)
+          case BT_AMP:
+            {
+              int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
+              if (tok <= 0) {
+                if (tok == XML_TOK_INVALID)
+                  *nextTokPtr = ptr;
+                return tok;
+              }
+              break;
+            }
+          case BT_LT:
+            *nextTokPtr = ptr;
+            return XML_TOK_INVALID;
+          default:
+            ptr += MINBPC(enc);
+            break;
+          }
+        }
+        ptr += MINBPC(enc);
+        if (ptr == end)
+          return XML_TOK_PARTIAL;
+        switch (BYTE_TYPE(enc, ptr)) {
+        case BT_S:
+        case BT_CR:
+        case BT_LF:
+          break;
+        case BT_SOL:
+          goto sol;
+        case BT_GT:
+          goto gt;
+        default:
+          *nextTokPtr = ptr;
+          return XML_TOK_INVALID;
+        }
+        /* ptr points to closing quote */
+        for (;;) {
+          ptr += MINBPC(enc);
+          if (ptr == end)
+            return XML_TOK_PARTIAL;
+          switch (BYTE_TYPE(enc, ptr)) {
+          CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+          case BT_S: case BT_CR: case BT_LF:
+            continue;
+          case BT_GT:
+          gt:
+            *nextTokPtr = ptr + MINBPC(enc);
+            return XML_TOK_START_TAG_WITH_ATTS;
+          case BT_SOL:
+          sol:
+            ptr += MINBPC(enc);
+            if (ptr == end)
+              return XML_TOK_PARTIAL;
+            if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+              *nextTokPtr = ptr;
+              return XML_TOK_INVALID;
+            }
+            *nextTokPtr = ptr + MINBPC(enc);
+            return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
+          default:
+            *nextTokPtr = ptr;
+            return XML_TOK_INVALID;
+          }
+          break;
+        }
+        break;
+      }
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<" */
+
+static
+int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
+                   const char **nextTokPtr)
+{
+#ifdef XML_NS
+  int hadColon;
+#endif
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  case BT_EXCL:
+    if ((ptr += MINBPC(enc)) == end)
+      return XML_TOK_PARTIAL;
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_MINUS:
+      return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+    case BT_LSQB:
+      return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+    }
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  case BT_QUEST:
+    return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_SOL:
+    return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+#ifdef XML_NS
+  hadColon = 0;
+#endif
+  /* we have a start-tag */
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+    case BT_COLON:
+      if (hadColon) {
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      hadColon = 1;
+      ptr += MINBPC(enc);
+      if (ptr == end)
+        return XML_TOK_PARTIAL;
+      switch (BYTE_TYPE(enc, ptr)) {
+      CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+      default:
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      break;
+#endif
+    case BT_S: case BT_CR: case BT_LF:
+      {
+        ptr += MINBPC(enc);
+        while (ptr != end) {
+          switch (BYTE_TYPE(enc, ptr)) {
+          CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+          case BT_GT:
+            goto gt;
+          case BT_SOL:
+            goto sol;
+          case BT_S: case BT_CR: case BT_LF:
+            ptr += MINBPC(enc);
+            continue;
+          default:
+            *nextTokPtr = ptr;
+            return XML_TOK_INVALID;
+          }
+          return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
+        }
+        return XML_TOK_PARTIAL;
+      }
+    case BT_GT:
+    gt:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_START_TAG_NO_ATTS;
+    case BT_SOL:
+    sol:
+      ptr += MINBPC(enc);
+      if (ptr == end)
+        return XML_TOK_PARTIAL;
+      if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_EMPTY_ELEMENT_NO_ATTS;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
+                       const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_NONE;
+  if (MINBPC(enc) > 1) {
+    size_t n = end - ptr;
+    if (n & (MINBPC(enc) - 1)) {
+      n &= ~(MINBPC(enc) - 1);
+      if (n == 0)
+        return XML_TOK_PARTIAL;
+      end = ptr + n;
+    }
+  }
+  switch (BYTE_TYPE(enc, ptr)) {
+  case BT_LT:
+    return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_AMP:
+    return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_CR:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_TRAILING_CR;
+    if (BYTE_TYPE(enc, ptr) == BT_LF)
+      ptr += MINBPC(enc);
+    *nextTokPtr = ptr;
+    return XML_TOK_DATA_NEWLINE;
+  case BT_LF:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_DATA_NEWLINE;
+  case BT_RSQB:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_TRAILING_RSQB;
+    if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+      break;
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return XML_TOK_TRAILING_RSQB;
+    if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+      ptr -= MINBPC(enc);
+      break;
+    }
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  INVALID_CASES(ptr, nextTokPtr)
+  default:
+    ptr += MINBPC(enc);
+    break;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: \
+      if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+        *nextTokPtr = ptr; \
+        return XML_TOK_DATA_CHARS; \
+      } \
+      ptr += n; \
+      break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_RSQB:
+      if (ptr + MINBPC(enc) != end) {
+         if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) {
+           ptr += MINBPC(enc);
+           break;
+         }
+         if (ptr + 2*MINBPC(enc) != end) {
+           if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) {
+             ptr += MINBPC(enc);
+             break;
+           }
+           *nextTokPtr = ptr + 2*MINBPC(enc);
+           return XML_TOK_INVALID;
+         }
+      }
+      /* fall through */
+    case BT_AMP:
+    case BT_LT:
+    case BT_NONXML:
+    case BT_MALFORM:
+    case BT_TRAIL:
+    case BT_CR:
+    case BT_LF:
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  *nextTokPtr = ptr;
+  return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "%" */
+
+static
+int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
+                        const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
+    *nextTokPtr = ptr;
+    return XML_TOK_PERCENT;
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_SEMI:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_PARAM_ENTITY_REF;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
+                          const char **nextTokPtr)
+{
+  if (ptr == end)
+    return XML_TOK_PARTIAL;
+  switch (BYTE_TYPE(enc, ptr)) {
+  CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_CR: case BT_LF: case BT_S:
+    case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR:
+      *nextTokPtr = ptr;
+      return XML_TOK_POUND_NAME;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return -XML_TOK_POUND_NAME;
+}
+
+static
+int PREFIX(scanLit)(int open, const ENCODING *enc,
+                    const char *ptr, const char *end,
+                    const char **nextTokPtr)
+{
+  while (ptr != end) {
+    int t = BYTE_TYPE(enc, ptr);
+    switch (t) {
+    INVALID_CASES(ptr, nextTokPtr)
+    case BT_QUOT:
+    case BT_APOS:
+      ptr += MINBPC(enc);
+      if (t != open)
+        break;
+      if (ptr == end)
+        return -XML_TOK_LITERAL;
+      *nextTokPtr = ptr;
+      switch (BYTE_TYPE(enc, ptr)) {
+      case BT_S: case BT_CR: case BT_LF:
+      case BT_GT: case BT_PERCNT: case BT_LSQB:
+        return XML_TOK_LITERAL;
+      default:
+        return XML_TOK_INVALID;
+      }
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
+                      const char **nextTokPtr)
+{
+  int tok;
+  if (ptr == end)
+    return XML_TOK_NONE;
+  if (MINBPC(enc) > 1) {
+    size_t n = end - ptr;
+    if (n & (MINBPC(enc) - 1)) {
+      n &= ~(MINBPC(enc) - 1);
+      if (n == 0)
+        return XML_TOK_PARTIAL;
+      end = ptr + n;
+    }
+  }
+  switch (BYTE_TYPE(enc, ptr)) {
+  case BT_QUOT:
+    return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_APOS:
+    return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_LT:
+    {
+      ptr += MINBPC(enc);
+      if (ptr == end)
+        return XML_TOK_PARTIAL;
+      switch (BYTE_TYPE(enc, ptr)) {
+      case BT_EXCL:
+        return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+      case BT_QUEST:
+        return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+      case BT_NMSTRT:
+      case BT_HEX:
+      case BT_NONASCII:
+      case BT_LEAD2:
+      case BT_LEAD3:
+      case BT_LEAD4:
+        *nextTokPtr = ptr - MINBPC(enc);
+        return XML_TOK_INSTANCE_START;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  case BT_CR:
+    if (ptr + MINBPC(enc) == end)
+      return -XML_TOK_PROLOG_S;
+    /* fall through */
+  case BT_S: case BT_LF:
+    for (;;) {
+      ptr += MINBPC(enc);
+      if (ptr == end)
+        break;
+      switch (BYTE_TYPE(enc, ptr)) {
+      case BT_S: case BT_LF:
+        break;
+      case BT_CR:
+        /* don't split CR/LF pair */
+        if (ptr + MINBPC(enc) != end)
+          break;
+        /* fall through */
+      default:
+        *nextTokPtr = ptr;
+        return XML_TOK_PROLOG_S;
+      }
+    }
+    *nextTokPtr = ptr;
+    return XML_TOK_PROLOG_S;
+  case BT_PERCNT:
+    return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+  case BT_COMMA:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_COMMA;
+  case BT_LSQB:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_OPEN_BRACKET;
+  case BT_RSQB:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return -XML_TOK_CLOSE_BRACKET;
+    if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
+      if (ptr + MINBPC(enc) == end)
+        return XML_TOK_PARTIAL;
+      if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) {
+        *nextTokPtr = ptr + 2*MINBPC(enc);
+        return XML_TOK_COND_SECT_CLOSE;
+      }
+    }
+    *nextTokPtr = ptr;
+    return XML_TOK_CLOSE_BRACKET;
+  case BT_LPAR:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_OPEN_PAREN;
+  case BT_RPAR:
+    ptr += MINBPC(enc);
+    if (ptr == end)
+      return -XML_TOK_CLOSE_PAREN;
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_AST:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_CLOSE_PAREN_ASTERISK;
+    case BT_QUEST:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_CLOSE_PAREN_QUESTION;
+    case BT_PLUS:
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_CLOSE_PAREN_PLUS;
+    case BT_CR: case BT_LF: case BT_S:
+    case BT_GT: case BT_COMMA: case BT_VERBAR:
+    case BT_RPAR:
+      *nextTokPtr = ptr;
+      return XML_TOK_CLOSE_PAREN;
+    }
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  case BT_VERBAR:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_OR;
+  case BT_GT:
+    *nextTokPtr = ptr + MINBPC(enc);
+    return XML_TOK_DECL_CLOSE;
+  case BT_NUM:
+    return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+#define LEAD_CASE(n) \
+  case BT_LEAD ## n: \
+    if (end - ptr < n) \
+      return XML_TOK_PARTIAL_CHAR; \
+    if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
+      ptr += n; \
+      tok = XML_TOK_NAME; \
+      break; \
+    } \
+    if (IS_NAME_CHAR(enc, ptr, n)) { \
+      ptr += n; \
+      tok = XML_TOK_NMTOKEN; \
+      break; \
+    } \
+    *nextTokPtr = ptr; \
+    return XML_TOK_INVALID;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+  case BT_NMSTRT:
+  case BT_HEX:
+    tok = XML_TOK_NAME;
+    ptr += MINBPC(enc);
+    break;
+  case BT_DIGIT:
+  case BT_NAME:
+  case BT_MINUS:
+#ifdef XML_NS
+  case BT_COLON:
+#endif
+    tok = XML_TOK_NMTOKEN;
+    ptr += MINBPC(enc);
+    break;
+  case BT_NONASCII:
+    if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) {
+      ptr += MINBPC(enc);
+      tok = XML_TOK_NAME;
+      break;
+    }
+    if (IS_NAME_CHAR_MINBPC(enc, ptr)) {
+      ptr += MINBPC(enc);
+      tok = XML_TOK_NMTOKEN;
+      break;
+    }
+    /* fall through */
+  default:
+    *nextTokPtr = ptr;
+    return XML_TOK_INVALID;
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+    case BT_GT: case BT_RPAR: case BT_COMMA:
+    case BT_VERBAR: case BT_LSQB: case BT_PERCNT:
+    case BT_S: case BT_CR: case BT_LF:
+      *nextTokPtr = ptr;
+      return tok;
+#ifdef XML_NS
+    case BT_COLON:
+      ptr += MINBPC(enc);
+      switch (tok) {
+      case XML_TOK_NAME:
+        if (ptr == end)
+          return XML_TOK_PARTIAL;
+        tok = XML_TOK_PREFIXED_NAME;
+        switch (BYTE_TYPE(enc, ptr)) {
+        CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+        default:
+          tok = XML_TOK_NMTOKEN;
+          break;
+        }
+        break;
+      case XML_TOK_PREFIXED_NAME:
+        tok = XML_TOK_NMTOKEN;
+        break;
+      }
+      break;
+#endif
+    case BT_PLUS:
+      if (tok == XML_TOK_NMTOKEN)  {
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_NAME_PLUS;
+    case BT_AST:
+      if (tok == XML_TOK_NMTOKEN)  {
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_NAME_ASTERISK;
+    case BT_QUEST:
+      if (tok == XML_TOK_NMTOKEN)  {
+        *nextTokPtr = ptr;
+        return XML_TOK_INVALID;
+      }
+      *nextTokPtr = ptr + MINBPC(enc);
+      return XML_TOK_NAME_QUESTION;
+    default:
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    }
+  }
+  return -tok;
+}
+
+static
+int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+                              const char **nextTokPtr)
+{
+  const char *start;
+  if (ptr == end)
+    return XML_TOK_NONE;
+  start = ptr;
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: ptr += n; break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_AMP:
+      if (ptr == start)
+        return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_LT:
+      /* this is for inside entity references */
+      *nextTokPtr = ptr;
+      return XML_TOK_INVALID;
+    case BT_LF:
+      if (ptr == start) {
+        *nextTokPtr = ptr + MINBPC(enc);
+        return XML_TOK_DATA_NEWLINE;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_CR:
+      if (ptr == start) {
+        ptr += MINBPC(enc);
+        if (ptr == end)
+          return XML_TOK_TRAILING_CR;
+        if (BYTE_TYPE(enc, ptr) == BT_LF)
+          ptr += MINBPC(enc);
+        *nextTokPtr = ptr;
+        return XML_TOK_DATA_NEWLINE;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_S:
+      if (ptr == start) {
+        *nextTokPtr = ptr + MINBPC(enc);
+        return XML_TOK_ATTRIBUTE_VALUE_S;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  *nextTokPtr = ptr;
+  return XML_TOK_DATA_CHARS;
+}
+
+static
+int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+                           const char **nextTokPtr)
+{
+  const char *start;
+  if (ptr == end)
+    return XML_TOK_NONE;
+  start = ptr;
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: ptr += n; break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_AMP:
+      if (ptr == start)
+        return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_PERCNT:
+      if (ptr == start) {
+        int tok =  PREFIX(scanPercent)(enc, ptr + MINBPC(enc),
+                                       end, nextTokPtr);
+        return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_LF:
+      if (ptr == start) {
+        *nextTokPtr = ptr + MINBPC(enc);
+        return XML_TOK_DATA_NEWLINE;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    case BT_CR:
+      if (ptr == start) {
+        ptr += MINBPC(enc);
+        if (ptr == end)
+          return XML_TOK_TRAILING_CR;
+        if (BYTE_TYPE(enc, ptr) == BT_LF)
+          ptr += MINBPC(enc);
+        *nextTokPtr = ptr;
+        return XML_TOK_DATA_NEWLINE;
+      }
+      *nextTokPtr = ptr;
+      return XML_TOK_DATA_CHARS;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  *nextTokPtr = ptr;
+  return XML_TOK_DATA_CHARS;
+}
+
+#ifdef XML_DTD
+
+static
+int PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
+                             const char **nextTokPtr)
+{
+  int level = 0;
+  if (MINBPC(enc) > 1) {
+    size_t n = end - ptr;
+    if (n & (MINBPC(enc) - 1)) {
+      n &= ~(MINBPC(enc) - 1);
+      end = ptr + n;
+    }
+  }
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    INVALID_CASES(ptr, nextTokPtr)
+    case BT_LT:
+      if ((ptr += MINBPC(enc)) == end)
+        return XML_TOK_PARTIAL;
+      if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) {
+        if ((ptr += MINBPC(enc)) == end)
+          return XML_TOK_PARTIAL;
+        if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) {
+          ++level;
+          ptr += MINBPC(enc);
+        }
+      }
+      break;
+    case BT_RSQB:
+      if ((ptr += MINBPC(enc)) == end)
+        return XML_TOK_PARTIAL;
+      if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
+        if ((ptr += MINBPC(enc)) == end)
+          return XML_TOK_PARTIAL;
+        if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+          ptr += MINBPC(enc);
+          if (level == 0) {
+            *nextTokPtr = ptr;
+            return XML_TOK_IGNORE_SECT;
+          }
+          --level;
+        }
+      }
+      break;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+  }
+  return XML_TOK_PARTIAL;
+}
+
+#endif /* XML_DTD */
+
+static
+int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+                       const char **badPtr)
+{
+  ptr += MINBPC(enc);
+  end -= MINBPC(enc);
+  for (; ptr != end; ptr += MINBPC(enc)) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_DIGIT:
+    case BT_HEX:
+    case BT_MINUS:
+    case BT_APOS:
+    case BT_LPAR:
+    case BT_RPAR:
+    case BT_PLUS:
+    case BT_COMMA:
+    case BT_SOL:
+    case BT_EQUALS:
+    case BT_QUEST:
+    case BT_CR:
+    case BT_LF:
+    case BT_SEMI:
+    case BT_EXCL:
+    case BT_AST:
+    case BT_PERCNT:
+    case BT_NUM:
+#ifdef XML_NS
+    case BT_COLON:
+#endif
+      break;
+    case BT_S:
+      if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) {
+        *badPtr = ptr;
+        return 0;
+      }
+      break;
+    case BT_NAME:
+    case BT_NMSTRT:
+      if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
+        break;
+    default:
+      switch (BYTE_TO_ASCII(enc, ptr)) {
+      case 0x24: /* $ */
+      case 0x40: /* @ */
+        break;
+      default:
+        *badPtr = ptr;
+        return 0;
+      }
+      break;
+    }
+  }
+  return 1;
+}
+
+/* This must only be called for a well-formed start-tag or empty element tag.
+Returns the number of attributes.  Pointers to the first attsMax attributes 
+are stored in atts. */
+
+static
+int PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
+                    int attsMax, ATTRIBUTE *atts)
+{
+  enum { other, inName, inValue } state = inName;
+  int nAtts = 0;
+  int open = 0; /* defined when state == inValue;
+                   initialization just to shut up compilers */
+
+  for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define START_NAME \
+      if (state == other) { \
+        if (nAtts < attsMax) { \
+          atts[nAtts].name = ptr; \
+          atts[nAtts].normalized = 1; \
+        } \
+        state = inName; \
+      }
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_NONASCII:
+    case BT_NMSTRT:
+    case BT_HEX:
+      START_NAME
+      break;
+#undef START_NAME
+    case BT_QUOT:
+      if (state != inValue) {
+        if (nAtts < attsMax)
+          atts[nAtts].valuePtr = ptr + MINBPC(enc);
+        state = inValue;
+        open = BT_QUOT;
+      }
+      else if (open == BT_QUOT) {
+        state = other;
+        if (nAtts < attsMax)
+          atts[nAtts].valueEnd = ptr;
+        nAtts++;
+      }
+      break;
+    case BT_APOS:
+      if (state != inValue) {
+        if (nAtts < attsMax)
+          atts[nAtts].valuePtr = ptr + MINBPC(enc);
+        state = inValue;
+        open = BT_APOS;
+      }
+      else if (open == BT_APOS) {
+        state = other;
+        if (nAtts < attsMax)
+          atts[nAtts].valueEnd = ptr;
+        nAtts++;
+      }
+      break;
+    case BT_AMP:
+      if (nAtts < attsMax)
+        atts[nAtts].normalized = 0;
+      break;
+    case BT_S:
+      if (state == inName)
+        state = other;
+      else if (state == inValue
+               && nAtts < attsMax
+               && atts[nAtts].normalized
+               && (ptr == atts[nAtts].valuePtr
+                   || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE
+                   || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE
+                   || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open))
+        atts[nAtts].normalized = 0;
+      break;
+    case BT_CR: case BT_LF:
+      /* This case ensures that the first attribute name is counted
+         Apart from that we could just change state on the quote. */
+      if (state == inName)
+        state = other;
+      else if (state == inValue && nAtts < attsMax)
+        atts[nAtts].normalized = 0;
+      break;
+    case BT_GT:
+    case BT_SOL:
+      if (state != inValue)
+        return nAtts;
+      break;
+    default:
+      break;
+    }
+  }
+  /* not reached */
+}
+
+static
+int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr)
+{
+  int result = 0;
+  itkExpatUnused(enc);
+  /* skip &# */
+  ptr += 2*MINBPC(enc);
+  if (CHAR_MATCHES(enc, ptr, ASCII_x)) {
+    for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
+      int c = BYTE_TO_ASCII(enc, ptr);
+      switch (c) {
+      case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4:
+      case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9:
+        result <<= 4;
+        result |= (c - ASCII_0);
+        break;
+      case ASCII_A: case ASCII_B: case ASCII_C: case ASCII_D: case ASCII_E: case ASCII_F:
+        result <<= 4;
+        result += 10 + (c - ASCII_A);
+        break;
+      case ASCII_a: case ASCII_b: case ASCII_c: case ASCII_d: case ASCII_e: case ASCII_f:
+        result <<= 4;
+        result += 10 + (c - ASCII_a);
+        break;
+      }
+      if (result >= 0x110000)
+        return -1;
+    }
+  }
+  else {
+    for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
+      int c = BYTE_TO_ASCII(enc, ptr);
+      result *= 10;
+      result += (c - ASCII_0);
+      if (result >= 0x110000)
+        return -1;
+    }
+  }
+  return checkCharRefNumber(result);
+}
+
+static
+int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end)
+{
+  itkExpatUnused(enc);
+  switch ((end - ptr)/MINBPC(enc)) {
+  case 2:
+    if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) {
+      switch (BYTE_TO_ASCII(enc, ptr)) {
+      case ASCII_l:
+        return ASCII_LT;
+      case ASCII_g:
+        return ASCII_GT;
+      }
+    }
+    break;
+  case 3:
+    if (CHAR_MATCHES(enc, ptr, ASCII_a)) {
+      ptr += MINBPC(enc);
+      if (CHAR_MATCHES(enc, ptr, ASCII_m)) {
+        ptr += MINBPC(enc);
+        if (CHAR_MATCHES(enc, ptr, ASCII_p))
+          return ASCII_AMP;
+      }
+    }
+    break;
+  case 4:
+    switch (BYTE_TO_ASCII(enc, ptr)) {
+    case ASCII_q:
+      ptr += MINBPC(enc);
+      if (CHAR_MATCHES(enc, ptr, ASCII_u)) {
+        ptr += MINBPC(enc);
+        if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
+          ptr += MINBPC(enc);
+          if (CHAR_MATCHES(enc, ptr, ASCII_t))
+            return ASCII_QUOT;
+        }
+      }
+      break;
+    case ASCII_a:
+      ptr += MINBPC(enc);
+      if (CHAR_MATCHES(enc, ptr, ASCII_p)) {
+        ptr += MINBPC(enc);
+        if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
+          ptr += MINBPC(enc);
+          if (CHAR_MATCHES(enc, ptr, ASCII_s))
+            return ASCII_APOS;
+        }
+      }
+      break;
+    }
+  }
+  return 0;
+}
+
+static
+int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2)
+{
+  for (;;) {
+    switch (BYTE_TYPE(enc, ptr1)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: \
+      if (*ptr1++ != *ptr2++) \
+        return 0;
+    LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2)
+#undef LEAD_CASE
+      /* fall through */
+      if (*ptr1++ != *ptr2++)
+        return 0;
+      break;
+    case BT_NONASCII:
+    case BT_NMSTRT:
+#ifdef XML_NS
+    case BT_COLON:
+#endif
+    case BT_HEX:
+    case BT_DIGIT:
+    case BT_NAME:
+    case BT_MINUS:
+      if (*ptr2++ != *ptr1++)
+        return 0;
+      if (MINBPC(enc) > 1) {
+        if (*ptr2++ != *ptr1++)
+          return 0;
+        if (MINBPC(enc) > 2) {
+          if (*ptr2++ != *ptr1++)
+            return 0;
+          if (MINBPC(enc) > 3) {
+            if (*ptr2++ != *ptr1++)
+              return 0;
+          }
+        }
+      }
+      break;
+    default:
+      if (MINBPC(enc) == 1 && *ptr1 == *ptr2)
+        return 1;
+      switch (BYTE_TYPE(enc, ptr2)) {
+      case BT_LEAD2:
+      case BT_LEAD3:
+      case BT_LEAD4:
+      case BT_NONASCII:
+      case BT_NMSTRT:
+#ifdef XML_NS
+      case BT_COLON:
+#endif
+      case BT_HEX:
+      case BT_DIGIT:
+      case BT_NAME:
+      case BT_MINUS:
+        return 0;
+      default:
+        return 1;
+      }
+    }
+  }
+  /* not reached */
+}
+
+static
+int PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1,
+                             const char *end1, const char *ptr2)
+{
+  itkExpatUnused(enc);
+  for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
+    if (ptr1 == end1)
+      return 0;
+    if (!CHAR_MATCHES(enc, ptr1, *ptr2))
+      return 0;
+  }
+  return ptr1 == end1;
+}
+
+static
+int PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
+{
+  const char *start = ptr;
+  for (;;) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: ptr += n; break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_NONASCII:
+    case BT_NMSTRT:
+#ifdef XML_NS
+    case BT_COLON:
+#endif
+    case BT_HEX:
+    case BT_DIGIT:
+    case BT_NAME:
+    case BT_MINUS:
+      ptr += MINBPC(enc);
+      break;
+    default:
+      return ptr - start;
+    }
+  }
+}
+
+static
+const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr)
+{
+  for (;;) {
+    switch (BYTE_TYPE(enc, ptr)) {
+    case BT_LF:
+    case BT_CR:
+    case BT_S:
+      ptr += MINBPC(enc);
+      break;
+    default:
+      return ptr;
+    }
+  }
+}
+
+static
+void PREFIX(updatePosition)(const ENCODING *enc,
+                            const char *ptr,
+                            const char *end,
+                            POSITION *pos)
+{
+  while (ptr != end) {
+    switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+    case BT_LEAD ## n: \
+      ptr += n; \
+      break;
+    LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+    case BT_LF:
+      pos->columnNumber = (unsigned)-1;
+      pos->lineNumber++;
+      ptr += MINBPC(enc);
+      break;
+    case BT_CR:
+      pos->lineNumber++;
+      ptr += MINBPC(enc);
+      if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
+        ptr += MINBPC(enc);
+      pos->columnNumber = (unsigned)-1;
+      break;
+    default:
+      ptr += MINBPC(enc);
+      break;
+    }
+    pos->columnNumber++;
+  }
+}
+
+#undef DO_LEAD_CASE
+#undef MULTIBYTE_CASES
+#undef INVALID_CASES
+#undef CHECK_NAME_CASE
+#undef CHECK_NAME_CASES
+#undef CHECK_NMSTRT_CASE
+#undef CHECK_NMSTRT_CASES
diff --git a/Utilities/ITK/Utilities/expat/xmltok_impl.h b/Utilities/ITK/Utilities/expat/xmltok_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..da0ea60a657d660770878804e3962426e84d58ef
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/xmltok_impl.h
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+enum {
+  BT_NONXML,
+  BT_MALFORM,
+  BT_LT,
+  BT_AMP,
+  BT_RSQB,
+  BT_LEAD2,
+  BT_LEAD3,
+  BT_LEAD4,
+  BT_TRAIL,
+  BT_CR,
+  BT_LF,
+  BT_GT,
+  BT_QUOT,
+  BT_APOS,
+  BT_EQUALS,
+  BT_QUEST,
+  BT_EXCL,
+  BT_SOL,
+  BT_SEMI,
+  BT_NUM,
+  BT_LSQB,
+  BT_S,
+  BT_NMSTRT,
+  BT_COLON,
+  BT_HEX,
+  BT_DIGIT,
+  BT_NAME,
+  BT_MINUS,
+  BT_OTHER, /* known not to be a name or name start character */
+  BT_NONASCII, /* might be a name or name start character */
+  BT_PERCNT,
+  BT_LPAR,
+  BT_RPAR,
+  BT_AST,
+  BT_PLUS,
+  BT_COMMA,
+  BT_VERBAR
+};
+
+#include <stddef.h>
diff --git a/Utilities/ITK/Utilities/expat/xmltok_ns.c b/Utilities/ITK/Utilities/expat/xmltok_ns.c
new file mode 100644
index 0000000000000000000000000000000000000000..fa78adffce1be1658ea7f899b81390e1085e590a
--- /dev/null
+++ b/Utilities/ITK/Utilities/expat/xmltok_ns.c
@@ -0,0 +1,98 @@
+const ENCODING *NS(XmlGetUtf8InternalEncoding)(void)
+{
+  return &ns(internal_utf8_encoding).enc;
+}
+
+const ENCODING *NS(XmlGetUtf16InternalEncoding)(void)
+{
+#if XML_BYTE_ORDER == 12
+  return &ns(internal_little2_encoding).enc;
+#elif XML_BYTE_ORDER == 21
+  return &ns(internal_big2_encoding).enc;
+#else
+  const short n = 1;
+  return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc;
+#endif
+}
+
+static
+const ENCODING *NS(encodings)[] = {
+  &ns(latin1_encoding).enc,
+  &ns(ascii_encoding).enc,
+  &ns(utf8_encoding).enc,
+  &ns(big2_encoding).enc,
+  &ns(big2_encoding).enc,
+  &ns(little2_encoding).enc,
+  &ns(utf8_encoding).enc /* NO_ENC */
+};
+
+static
+int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
+                       const char **nextTokPtr)
+{
+  return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr);
+}
+
+static
+int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
+                       const char **nextTokPtr)
+{
+  return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr);
+}
+
+int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name)
+{
+  int i = getEncodingIndex(name);
+  if (i == UNKNOWN_ENC)
+    return 0;
+  SET_INIT_ENC_INDEX(p, i);
+  p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
+  p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
+  p->initEnc.updatePosition = initUpdatePosition;
+  p->encPtr = encPtr;
+  *encPtr = &(p->initEnc);
+  return 1;
+}
+
+static
+const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
+{
+#define ENCODING_MAX 128
+  char buf[ENCODING_MAX];
+  char *p = buf;
+  int i;
+  XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
+  if (ptr != end)
+    return 0;
+  *p = 0;
+  if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2)
+    return enc;
+  i = getEncodingIndex(buf);
+  if (i == UNKNOWN_ENC)
+    return 0;
+  return NS(encodings)[i];
+}
+
+int NS(XmlParseXmlDecl)(int isGeneralTextEntity,
+                        const ENCODING *enc,
+                        const char *ptr,
+                        const char *end,
+                        const char **badPtr,
+                        const char **versionPtr,
+                        const char **versionEndPtr,
+                        const char **encodingName,
+                        const ENCODING **encoding,
+                        int *standalone)
+{
+  return doParseXmlDecl(NS(findEncoding),
+                        isGeneralTextEntity,
+                        enc,
+                        ptr,
+                        end,
+                        badPtr,
+                        versionPtr,
+                        versionEndPtr,
+                        encodingName,
+                        encoding,
+                        standalone);
+}
diff --git a/Utilities/ITK/Utilities/gdcm/.cvsignore b/Utilities/ITK/Utilities/gdcm/.cvsignore
new file mode 100644
index 0000000000000000000000000000000000000000..55f3c305b346534da50cc956633188a67442ba98
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/.cvsignore
@@ -0,0 +1,37 @@
+Makefile.in
+Makefile
+config.cache
+config.guess
+config.log
+config.status
+config.sub
+configure
+libtool
+ltmain.sh
+aclocal.m4
+autom4te.cache
+*.pyc
+build
+dist
+MANIFEST
+gdcm*.tar.gz
+gdcm.spec
+*Debug*
+*Release*
+*gdcmData*
+*.ncb
+*.opt
+*Python.cxx
+*lib*
+CMakeCCompiler.cmake
+CMakeCXXCompiler.cmake
+CMakeCache.txt
+CMakeOutput.log
+CMakeSystem.cmake
+CMakeTmp
+DartConfiguration.tcl
+DartTestfile.txt
+cmake.check_cache
+cmake.check_depends
+cmake.depends
+gdcmConfigure.h
diff --git a/Utilities/ITK/Utilities/gdcm/AUTHORS b/Utilities/ITK/Utilities/gdcm/AUTHORS
new file mode 100644
index 0000000000000000000000000000000000000000..ffda87cb491ce0e126684755793b3116f39ff7e2
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/AUTHORS
@@ -0,0 +1,8 @@
+Boix Eric (Creatis)
+Florez Leonardo (Creatis/Theralys)
+Ibanez Luis (Kitware)
+Malaterre Mathieu (Kitware)
+Olart Emmanuel (Theralys)
+Regrain Benoit (Creatis)
+Rouet Jean-Michel (Philips)
+Roux Jean-Pierre (Creatis)
diff --git a/Utilities/ITK/Utilities/gdcm/CMake/CTestCustom.ctest.in b/Utilities/ITK/Utilities/gdcm/CMake/CTestCustom.ctest.in
new file mode 100644
index 0000000000000000000000000000000000000000..58cad9a5079b2d39f3ff525c0ebe2f59a5411118
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/CMake/CTestCustom.ctest.in
@@ -0,0 +1,14 @@
+SET(CTEST_CUSTOM_WARNING_EXCEPTION
+  ${CTEST_CUSTOM_WARNING_EXCEPTION}
+  "comparison is always (true|false) due to limited range of data type"
+  "ld: warning prebinding disabled because \\((__TEXT|__DATA|__LINKEDIT) segment \\(address = 0x[a-f0-9]+ size = 0x[a-f0-9]+\\) of (.*) overlaps with (__LINKEDIT|__TEXT|__DATA) segment \\(address = 0x[a-f0-9]+ size = 0x[a-f0-9]+\\) of (.*)"
+  "ld: warning prebinding disabled because dependent library: (.*).dylib is not prebound"
+  "gdcmjasper/(.*) warning: statement not reached"
+  "warning: string length `[0-9]+' is greater than the length `509' ISO C89 compilers are required to support"
+  "warning: string length '[0-9]+' is greater than the length '509' ISO C89 compilers are required to support"
+  "/.../gdcm/src/gdcmjasper/src/libjasper/(.*)"
+  "\"/.../gdcm/src/gdcmjpeg/jccolor.c\", line 107: warning: integer overflow detected: op \"<<\""
+  "Warning W8004.*gdcmjasper[\\]src[\\]libjasper.*"
+  )
+
+
diff --git a/Utilities/ITK/Utilities/gdcm/CMake/FindDicom3Tools.cmake b/Utilities/ITK/Utilities/gdcm/CMake/FindDicom3Tools.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..d8176f4d00ec723c4c13a26cbae0559914ea9c91
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/CMake/FindDicom3Tools.cmake
@@ -0,0 +1,34 @@
+# 
+# this module looks for Dicom3Tools, well right now only dciodvfy
+#
+# DCIODVFY_EXECUTABLE - the full path to the dciodvfy
+# DCIODVFY_FOUND      - If false, don't attempt to use dciodvfy
+
+# dicom3tools are funny to build you'll need imake
+# Anyway in order not to pollute your system, you can do an in-source build 
+# and install which should be clean enough:
+# 
+# ./Configure
+# imake -I./config -DInstallInTopDir
+# make World
+# make install (will copy in ./bin)
+#
+# then all you need to do is export an env var DICOM3TOOLS pointing to that dir
+
+FIND_PROGRAM(DCIODVFY_EXECUTABLE
+  dciodvfy
+  "/tmp/"
+  "$ENV{DICOM3TOOLS}/bin"
+  "$ENV{DICOM3TOOLS}/bin/1.2.6.8."
+  )
+
+MARK_AS_ADVANCED(
+  DCIODVFY_EXECUTABLE
+  )
+
+IF (NOT DCIODVFY_EXECUTABLE)
+  SET(DCIODVFY_FOUND "NO")
+ELSE (NOT DCIODVFY_EXECUTABLE)
+  SET(DCIODVFY_FOUND "YES")
+ENDIF (NOT DCIODVFY_EXECUTABLE)
+
diff --git a/Utilities/ITK/Utilities/gdcm/CMake/FindRsync.cmake b/Utilities/ITK/Utilities/gdcm/CMake/FindRsync.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..6e8c6f896fa94c2f8167551e3e0c434786586538
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/CMake/FindRsync.cmake
@@ -0,0 +1,19 @@
+#
+# This module finds if rsync is installed
+#
+#  RSYNC_EXECUTABLE         = full path to the pike binary
+#
+# Typical usage for gdcm is:
+# rsync -avH --delete [options] rsync.creatis.insa-lyon.fr::module localdir
+# Compression option is: -z
+
+FIND_PROGRAM(RSYNC_EXECUTABLE
+  NAMES rsync
+  PATHS
+  /usr/bin
+  /usr/local/bin
+  )
+
+MARK_AS_ADVANCED(
+  RSYNC_EXECUTABLE
+  )
diff --git a/Utilities/ITK/Utilities/gdcm/CMake/gdcmTestFUNCTION.cxx b/Utilities/ITK/Utilities/gdcm/CMake/gdcmTestFUNCTION.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..cceaa2e0a46c56f3513cb4c7bb42b17c7fc09a0b
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/CMake/gdcmTestFUNCTION.cxx
@@ -0,0 +1,38 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmTestFUNCTION.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/02 18:26:18 $
+  Version:   $Revision: 1.2 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+// Minimal test for existence of __FUNCTION__ pseudo-macro
+#include <string.h>
+
+int TestFUNCTION()
+{
+#ifdef __BORLANDC__
+  #ifndef __FUNCTION__
+    #define __FUNCTION__ __FUNC__
+  #endif
+#endif
+  const char *f = __FUNCTION__;
+  int r = strcmp( "TestFUNCTION", f);
+  return r;
+}
+ 
+int main()
+{
+  return TestFUNCTION();
+}
+
diff --git a/Utilities/ITK/Utilities/gdcm/CMake/gdcmValgrind.supp b/Utilities/ITK/Utilities/gdcm/CMake/gdcmValgrind.supp
new file mode 100644
index 0000000000000000000000000000000000000000..f152efeb3a06b9880182af6153ceb25a73c4c470
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/CMake/gdcmValgrind.supp
@@ -0,0 +1,129 @@
+{
+   <insert a suppression name here>
+   Memcheck:Param
+   write(buf)
+   fun:__write_nocancel
+   obj:/usr/X11R6/lib/libX11.so.6.2
+   fun:_X11TransWrite
+   obj:/usr/X11R6/lib/libX11.so.6.2
+}
+{
+   <insert a suppression name here>
+   Memcheck:Free
+   fun:free
+   fun:__GI__dl_deallocate_tls
+   fun:vgArch_thread_exit
+   fun:thread_exit_wrapper
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:__cxa_get_globals
+   fun:_ZSt18uncaught_exceptionv
+   fun:_ZNSo6sentryD1Ev
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:XextCreateExtension
+   fun:__glXInitialize
+   fun:glXGetConfig
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:calloc
+   fun:_dlerror_run
+   fun:dlsym
+   fun:__errno_location
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:OpenDriver
+   fun:__glXRegisterExtensions
+   fun:__glXNewIndirectAPI
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:_dl_map_object_internal
+   fun:openaux
+   fun:_dl_catch_error_internal
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:_dl_map_object_deps_internal
+   fun:dl_open_worker
+   fun:_dl_catch_error_internal
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:__glXstrdup
+   fun:OpenDriver
+   fun:__glXRegisterExtensions
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:_dl_map_object_internal
+   fun:dl_open_worker
+   fun:_dl_catch_error_internal
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:_dl_new_object
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object_internal
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:dl_open_worker
+   fun:_dl_catch_error_internal
+   fun:__GI__dl_open
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:calloc
+   fun:_dl_check_map_versions_internal
+   fun:dl_open_worker
+   fun:_dl_catch_error_internal
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:calloc
+   fun:_dl_new_object
+   fun:_dl_map_object_from_fd
+   fun:_dl_map_object_internal
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:__glXNewIndirectAPI
+   fun:glXMakeCurrent
+   fun:_ZN22vtkXOpenGLRenderWindow11MakeCurrentEv
+}
+{
+   <insert a suppression name here>
+   Memcheck:Leak
+   fun:malloc
+   fun:__fgl_glapi_add_entrypoint
+   fun:__driRegisterExtensions
+   fun:__glXRegisterExtensions
+}
diff --git a/Utilities/ITK/Utilities/gdcm/CMakeLists.txt b/Utilities/ITK/Utilities/gdcm/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..529ba7033d1a61848b5c636f9bdb394ecb98e4d1
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/CMakeLists.txt
@@ -0,0 +1,151 @@
+PROJECT(GDCM)
+CMAKE_MINIMUM_REQUIRED(VERSION 2.0)
+# okay in fact you need at least cmake 2.0.4 to get swig working properly
+
+#-----------------------------------------------------------------------------
+# GDCM version number, usefull for packaging and doxygen doc:
+SET(GDCM_MAJOR_VERSION 1)
+SET(GDCM_MINOR_VERSION 2)
+SET(GDCM_BUILD_VERSION 0)
+SET(GDCM_VERSION 
+    "${GDCM_MAJOR_VERSION}.${GDCM_MINOR_VERSION}.${GDCM_BUILD_VERSION}")
+
+#-----------------------------------------------------------------------------
+# datadir in CMake:
+SET(GDCM_DATA_DIR "/share/gdcm/" CACHE INTERNAL 
+  "Install location for data (relative to prefix).")
+MARK_AS_ADVANCED(GDCM_DATA_DIR)
+
+#-----------------------------------------------------------------------------
+# Provide compatibility options.
+OPTION(GDCM_LEGACY_REMOVE "Remove all legacy code completely." OFF)
+OPTION(GDCM_LEGACY_SILENT "Silence all legacy code messages." OFF)
+MARK_AS_ADVANCED(GDCM_LEGACY_REMOVE GDCM_LEGACY_SILENT)
+
+#-----------------------------------------------------------------------------
+# Build shared lib by default
+SET(GDCM_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
+
+#OPTION(GDCM_DEBUG "Turn verbosity of some statement ON." OFF)
+#MARK_AS_ADVANCED(GDCM_DEBUG)
+SET(GDCM_DEBUG 0)
+
+#-----------------------------------------------------------------------------
+# Test if compiler defines the pseudo-macro __FUNCTION__
+IF("GDCM_COMPILER_HAS_FUNCTION" MATCHES "^GDCM_COMPILER_HAS_FUNCTION$")
+  MESSAGE(STATUS "Checking support for __FUNCTION__ in compiler")
+  TRY_COMPILE(GDCM_COMPILER_HAS_FUNCTION
+              ${GDCM_BINARY_DIR}/CMakeTmp/Function
+              ${GDCM_SOURCE_DIR}/CMake/gdcmTestFUNCTION.cxx
+              OUTPUT_VARIABLE OUTPUT)
+  IF(GDCM_COMPILER_HAS_FUNCTION)
+    MESSAGE(STATUS "Checking support for __FUNCTION__ -- yes")
+    SET(GDCM_COMPILER_HAS_FUNCTION 1 CACHE INTERNAL "Support for extension C __FUNCTION__")
+    WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeOutput.log
+      "Determining if the C compiler supports __FUNCTION__ "
+      "passed with the following output:\n"
+      "${OUTPUT}\n" APPEND)
+  ELSE(GDCM_COMPILER_HAS_FUNCTION)
+    MESSAGE(STATUS "Checking support for __FUNCTION__ -- no")
+    SET(GDCM_COMPILER_HAS_FUNCTION 0 CACHE INTERNAL "Support for extension C __FUNCTION__")
+    WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeError.log
+      "Determining if the C compiler supports __FUNCTION__ "
+      "failed with the following output:\n"
+      "${OUTPUT}\n" APPEND)
+  ENDIF(GDCM_COMPILER_HAS_FUNCTION)
+ENDIF("GDCM_COMPILER_HAS_FUNCTION" MATCHES "^GDCM_COMPILER_HAS_FUNCTION$")
+
+#-----------------------------------------------------------------------------
+# Build directory on which many applications depend
+SUBDIRS(
+  Dicts
+  src
+)
+
+# Set the place for the public dictionary, must be set before gdcmConfigure.h
+SET( GDCM_PUB_DICT_PATH "${CMAKE_INSTALL_PREFIX}${GDCM_DATA_DIR}")
+
+#-----------------------------------------------------------------------------
+# Big endian thing:
+INCLUDE (${CMAKE_ROOT}/Modules/TestBigEndian.cmake)
+TEST_BIG_ENDIAN(GDCM_WORDS_BIGENDIAN)
+
+INCLUDE (${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake)
+CHECK_INCLUDE_FILE("stdint.h"       CMAKE_HAVE_STDINT_H)
+IF(UNIX) #Avoid polluting Win32 cmakecache
+  CHECK_INCLUDE_FILE("inttypes.h"     CMAKE_HAVE_INTTYPES_H)
+ENDIF(UNIX)
+
+# Check if header file exists and add it to the list.
+INCLUDE (${CMAKE_ROOT}/Modules/CheckIncludeFiles.cmake)
+MACRO(CHECK_INCLUDE_FILE_CONCAT FILE VARIABLE)
+  CHECK_INCLUDE_FILES("${GDCM_INCLUDES};${FILE}" ${VARIABLE})
+  IF(${VARIABLE})
+    SET(GDCM_INCLUDES ${GDCM_INCLUDES} ${FILE})
+  ENDIF(${VARIABLE})
+ENDMACRO(CHECK_INCLUDE_FILE_CONCAT)
+
+# Need those header for GetMacAddress in Util
+# This is tricky as you need to figure out the proper order to
+# test the inclusion of files
+CHECK_INCLUDE_FILE_CONCAT("unistd.h"       CMAKE_HAVE_UNISTD_H)
+CHECK_INCLUDE_FILE_CONCAT("stdlib.h"       CMAKE_HAVE_STDLIB_H)
+IF(UNIX) #Avoid polluting Win32 cmakecache
+  CHECK_INCLUDE_FILE_CONCAT("sys/ioctl.h"    CMAKE_HAVE_SYS_IOCTL_H)
+  CHECK_INCLUDE_FILE_CONCAT("sys/socket.h"   CMAKE_HAVE_SYS_SOCKET_H)
+  CHECK_INCLUDE_FILE_CONCAT("sys/sockio.h"   CMAKE_HAVE_SYS_SOCKIO_H)
+  CHECK_INCLUDE_FILE_CONCAT("net/if.h"       CMAKE_HAVE_NET_IF_H)
+  CHECK_INCLUDE_FILE_CONCAT("netinet/in.h"   CMAKE_HAVE_NETINET_IN_H)
+  CHECK_INCLUDE_FILE_CONCAT("net/if_dl.h"    CMAKE_HAVE_NET_IF_DL_H)
+  CHECK_INCLUDE_FILE_CONCAT("net/if_arp.h"   CMAKE_HAVE_NET_IF_ARP_H)
+ENDIF(UNIX)
+
+#-----------------------------------------------------------------------------
+# Test if os defines a lenght for sockaddr
+# only doing the test when we have sys/socket
+IF( ${CMAKE_HAVE_SYS_SOCKET_H} )
+  IF("HAVE_SA_LEN" MATCHES "^HAVE_SA_LEN$")
+    STRING(ASCII 35 POUND)
+    FILE(WRITE ${GDCM_BINARY_DIR}/CMakeTmp/gdcmTestHAVESALEN.c
+      "${POUND}include <sys/types.h>\n"
+      "${POUND}include <sys/socket.h>\n"
+      "int main() { struct sockaddr sa; sa.sa_len = 0; }")
+    MESSAGE(STATUS "Checking if ifreq has a sa_len")
+    TRY_COMPILE(HAVE_SA_LEN
+      ${GDCM_BINARY_DIR}
+      ${GDCM_BINARY_DIR}/CMakeTmp/gdcmTestHAVESALEN.c
+      OUTPUT_VARIABLE OUTPUT)
+    IF(HAVE_SA_LEN)
+      MESSAGE(STATUS "Checking if ifreq has a sa_len -- yes")
+      SET(HAVE_SA_LEN 1 CACHE INTERNAL "Support if ifreq has a sa_len")
+      WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeOutput.log
+        "Determining if ifreq has a sa_len"
+        "passed with the following output:\n"
+        "${OUTPUT}\n" APPEND)
+    ELSE(HAVE_SA_LEN)
+      MESSAGE(STATUS "Checking if ifreq has a sa_len -- no")
+      SET(HAVE_SA_LEN 0 CACHE INTERNAL "Support if ifreq has a sa_len")
+      WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeError.log
+        "Determining if ifreq has a sa_len"
+        "failed with the following output:\n"
+        "${OUTPUT}\n" APPEND)
+    ENDIF(HAVE_SA_LEN)
+  ENDIF("HAVE_SA_LEN" MATCHES "^HAVE_SA_LEN$")
+ENDIF( ${CMAKE_HAVE_SYS_SOCKET_H} )
+
+#-----------------------------------------------------------------------------
+# Do the OpenJPEG export thing
+IF (WIN32)
+  IF (BUILD_SHARED_LIBS)
+    SET(OPJ_EXPORTS 1)
+  ELSE (BUILD_SHARED_LIBS)
+    SET(OPJ_STATIC 1)
+  ENDIF (BUILD_SHARED_LIBS)
+ENDIF (WIN32)
+
+
+CONFIGURE_FILE(${GDCM_SOURCE_DIR}/gdcmConfigure.h.in
+               ${GDCM_BINARY_DIR}/gdcmConfigure.h @ONLY IMMEDIATE)
+
+INSTALL_FILES(/include/InsightToolkit/gdcm/src .h gdcmConfigure.h)
+
diff --git a/Utilities/ITK/Utilities/gdcm/ChangeLog b/Utilities/ITK/Utilities/gdcm/ChangeLog
new file mode 100644
index 0000000000000000000000000000000000000000..d1ced5d25ff7cc7b61603ec049e41a37a328992e
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/ChangeLog
@@ -0,0 +1,4121 @@
+Thu Aug 25 16:59:49 2005 by jpr
+   gdcmBinEntry.cxx
+   Now Print displays the BinEntry Content (if it's printable, and loaded)
+   Usefull for a lot od Implicit VR 'Bin'Entry (if we knew there VR, they wouldn't
+   be Bin ...)
+   Appreciate the difference having a look at PrintFile result for
+   gdcmData/SIEMENS_MAGNETOM-12-MONO2-FileSeq0.dcm.
+
+Thu Aug 25 16:55:47 2005 by jpr
+   gdcmUtil.cxx
+   Add methods to check the 'printability' of a bin area
+
+Thu Aug 25 15:45:40 2005  by jpr
+  gdcmBinEntry.cxx 
+  According to Mathieu's suggestion, Print now display FL BinEntries in a human
+  readable form
+
+Thu Aug 25 15:12:43 2005 by jpr
+   gdcmDocEntry.cxx
+   According to Mathieu's suggestion, *all* the elements 0x000
+   are now named 'Group Length' (even if they belong to a Shadow Group')
+
+Wed Aug 24 14:09:13 2005 by jpr
+  gdcmDocEntry.cxx,h, gdcmDocEntrySet.cxx,h
+  Removal of QD patch for Private Sequence + Immplicit VR.
+   Add a clean solution (Backtracking if an Item Starter is found
+    out of any SQItem)
+
+Tue Aug 23 14:57:49 2005 by jpr
+   gdcmDocument.cxx
+   Brutal patch, waiting till we find a clever way to guess
+   if a doc entry is a Sequence,
+        - when it's odd number
+		  - and the file is Implicit VR Transfert Syntax
+It solves temporarily some Philips Medical Systems image problems
+
+Mon Aug 22 18:17:54 200 by jpr
+   gdcmUtil.cxx
+   Save a *few* microseconds at run time : inline method Util::GetVersion()
+   ;-)
+
+Tue Aug 23 14:58:49 2005 by jpr
+   gdcmSeqEntry.cxx, gdcmDocEntry.cxx
+   Improve 'Print' methods
+
+Sat Aug 20 11:10:24 2005by jpr
+   TestWriteSimple.cxx
+   Use new style FileHelper contructor
+
+Sat Aug 20 11:04:50 2005 by jpr
+   gdcmFileHelper.cxx
+   FileHelper::Initialize() doesn't call GrabInformationFromFile(),
+   in order not to do the job twice when using new style FileHelper Constructor.
+
+Fri Aug 19 18:31:07 2005 by malaterre
+  gdcmCommon.h
+  ENH: Provide a GetVersion function, apparently need for python
+
+Fri Aug 19 15:12:15 2005 by jpr
+   gdcmFileHelper.cxx
+   Initialize UserFunction pointer to 0, even for 'deprecated' form 
+	of constructor.
+
+Sat Jul 30 20:27:00 2005 by jpr
+   gdcmFileHelper.cxx, gdcmPixelReadConvertor.cxx
+      User is now allowed to pass a Pointer to a function of his own
+      to allow modification of pixel order (i.e. : Mirror, TopDown, )
+      to gdcm::FileHeleper, using SetUserFunction(userSuppliedFunction)
+      described as : void userSuppliedFunction(uint8_t *im, gdcm::File *f);
+      NB : the "uint8_t *" type of first param is just for prototyping.
+        User will Cast it according what he founds with f->GetPixelType()
+        See ctkgdcmSerieViewer for an example
+
+Sat Jul 30 20:13:24 2005 by jpr
+   gdcmSerieHelper.cxx
+   Add SerieHelper::IsCoherent() method to allow checking that the files with same
+   Serie UID have the same sizes and pixel type.
+	
+Fri Jul 29 17:07:16 2005 by jpr
+   gdcmSerieHelper.cxx
+   User may now use
+      SetSortOrderToDirect() or SetSortOrderToReverse()
+   to choose the ways the File* will be sorted.
+
+Thu Jul 21 06:55:50 2005 by jpr
+   AnonymizeDicomDir.cxx, AnomymizeNoLoad.cxx, PrintFile.cxx, PrintDicomDir.cxx
+   Unify user interface
+
+Thu Jul 21 06:55:30 2005 by jpr
+   exSerieHelper.cxx
+   Add an example of use for SerieHelper
+
+Thu Jul 21 07:00:15 2005 by jpr
+   gdcmSerieHelper.cxx
+   Extend 'Restriction' syntax :
+   void SerieHelper::AddRestriction(uint16_t group, uint16_t elem,
+                                    std::string const &value, int op)
+   op belongs to :
+   /// \brief comparaison operators
+   enum CompOperators {
+      GDCM_EQUAL = 0,
+      GDCM_DIFFERENT,
+      GDCM_GREATER,
+      GDCM_GREATEROREQUAL,
+      GDCM_LESS,
+      GDCM_LESSOREQUAL
+   };
+
+Wed Jul 20 15:39:00 2005  by jpr
+   AnonymizeNoLoad.cxx
+   AnonymizeNoLoad user can now ask for anonymization of 'BinEntries'
+   (e.g. Private entries when the TS is Implict VR)
+   AnonymizeNoLoad filein=... rubout=0x0009-0x0001,0x0013-0x1100
+   Thx to Luca Picello for reporting pb and supplying data to fix the bug.
+
+Wed Jul 20 16:49:41 2005 by jpr
+   gdcmFile.cxx
+   Use GDCM_LEGACY for DicomDir, as well
+
+Wed Jul 20 15:31:01 2005 by jpr
+   gdcmFile.cxx
+   We can now anonymize 'BinEntries' as well
+
+Wed Jul 20 15:29:42 2005 by jpr
+   gdcmArgMgr.cxx
+   Add ArgMgrGetXInt16Enum to decode from the command line pairs of unsigned int
+   16, written in hexadecimal.
+   (usefull to allow terminal user to pass the (private) elements he wants to
+   anonymize)
+
+Tue Jul 19 17:25:53 2005  by jpr
+   gdcmFile.cxx
+   Add some comments on the 'Patient Position'
+
+Tue Jul 19 11:04:58 2005 by jpr
+   gdcmSerieHelper.cxx
+   Add SerieHelper::AddGdcmFile(File *header) method.
+    * \brief add a gdcm::File to the first (and supposed to be unique) list
+    *        of the gdcm::SerieHelper.
+    * \warning : this method should be used by aware users only!
+    *            User is supposed to know the files he want to deal with
+    *           and consider them they belong to the same Serie
+    *           (even if their Serie UID is different)
+    *           user will probabely OrderFileList() this list (actually, ordering
+    *           user choosen gdm::File is the sole interest of this method)
+    *           Moreover, using vtkGdcmReader::SetCoherentFileList() will avoid
+    *           vtkGdcmReader parsing twice the same files.
+    *           *no* coherence check is performed, but those specified
+    *           by SerieHelper::AddRestriction()
+
+Mon Jul 18 12:20:20 2005 by jpr
+   gdcmCommon.cxx
+   In order to prepare the future extension of SerieHelper::AddRestriction (key,
+   string, operator)
+   operator = { EQUAL, DIFFERENT, LESS, LESSOREQUAL, GREATER, GREATEROOREQUAL}
+   add method
+   bool Util::CompareDicomString(const std::string &s1, const char *s2, int op)
+
+Sun Jul 17 06:27:49 2005 by jpr
+   gdcmSerieHelper.cxx
+   Use new style for Loading files
+
+Tue Jul 12 19:08:12 2005 by jpr
+   gdcmCommon.cxx, gdcmSQItem.cxx
+   To speed up DicomDir, instead of copying -and removing the source afterwards-
+   each entry of the SQItem (found after gdcm::Document parsing) towards
+   the gdcm::Object  belonging to the gdcm::DicomDir, we just copy
+   the chained list itself.
+
+Tue Jul 12 16:55:43 2005 by jpr
+   AnonymizeNoLoad.cxx
+   AnonymizeNoLoad has now one more option :
+   dirin=
+   to give the (single Patient) directory name whose content we want to anonymize.
+
+Mon Jul 11 10:20:25 2005 by jpr
+   gdcmDicomDirStudy.cxx
+   Reorder methods
+
+Fri Jul 8 21:07:12 2005 by jpr
+   gdcmDicomDir...
+   Add the VISIT object within DicomDir
+
+Fri Jul 8 12:15:08 2005 by jpr
+   gdcmDicomDir...
+   Use new style for DicomDir loading
+
+Fri Jul 8 16:36:48 2005 by jpr
+   gdcmFileHelper.cxx
+   To remain unimpared, gdcm::FileHelper class needs also its
+   void FileHelper::SetLoadMode(int loadMode)
+   void FileHelper::SetFileName(std::string const &fileName)
+   bool FileHelper::Load()
+
+Thu Jul 7 19:31:53 2005 by jpr
+   Example/*.cxx
+   Begin of kosherization of Example
+   New 'gdcm2' style.
+
+Thu Jul 7 18:37:40 2005 by jpr
+   gdcmDocument.cxx
+   On the way to gdcm2 ...
+   Now, the stand way to use a file is :
+   gdcm::File *f = new gdcm::File();
+   f->SetLoadMode ( user say here what he wants *not* to load );
+   f->SetFileName("myFile.gdcm");
+   f->Load();
+   Old styles are kept, not to break the C++ API.
+      - gdcm::File *f = new gdcm::File("myFile.gdcm");
+      - f->Load("myFile.gdcm");
+   Due to the syntaxic abilities of Python maybe some troubles will occur
+   (not sure ...)
+
+Thu Jul 7 15:55:39 2005 by jpr
+  gdcmDocument.cxx
+  Comment out the time consuming, never used/useless
+  'Extended tag' stuff for Sequence embedded Entries
+
+Thu Jul 7 15:11:38 2005 by jpr
+  gdcmDocument.cxx
+  Move code lines LTTG so save some CPU time.
+  (hope so)
+
+Tue Jun 7 13:12:10 2005 CEST by jpr
+   Example/*.cxx
+   Use Argument Manager in 'utilities'
+
+Thu Jul 7 12:12:32 2005 by jpr
+   gdcmFile.cxx
+   Due to something stupid in the gdcm::File constructor, the file was parsed 
+   twice when we used old style, e.g :
+   gdcm::File *f = new gdcm::File(fileName);
+   instead of new style, e.g. :
+   gdcm::File *f = new gdcm::File( );
+   f->SetLoadMode ( choose what you want *not* to load here );
+   f->Load( filename );
+
+Wed Jul 6 11:53:43 2005 by jpr
+   TestAllReadCompareDicom.cxx, TestReadWriteReadCompare.cxx
+   Now TestAllReadCompareDicom.cxx TestReadWriteReadCompare.cxx accept a third
+   param, in order not to have to recompile to gdcm::Debug::DebugOn().
+
+Wed Jul 6 17:18:42 2005 by jpr
+   gdcmDocument.cxx
+   According to Mathieu's requirement, Load twice the same file keeps the rseult of
+   the first Load (instead of doing it twice)
+
+Wed Jul 6 11:25:12 2005 by jpr
+   gdcmDocument.cxx
+   - Clean out the Entries if a Document is parsed more than once
+   - Uncomment (usefull) warning messages
+
+Wed Jul 6 10:42:33 2005 by jpr
+   gdcmDocument.cxx
+   - Comment out a for the moment too much verbose warning message.
+   - Delay some statement as late as possible, to save some CPU time when they're
+     useless
+  
+Wed Jul 6 13:01:08 2005 by jpr
+   gdcmFile.cxx
+   Now gdcmFile::Load() returns false if file is not gdcm parsable
+   Only gdcmDocument::Load() did it, before.
+   Thx to Benoit for reporting bug
+
+Sun Jul 3 14:42:04 2005 by jpr
+   gdcmDocument.cxx
+   Should avoid some troubles with 'no length' SQItems within 'true length'
+   Sequences.
+   Thx to Loic Boussel for providing data to fix the bug.
+
+Sun Jul 3 14:42:04 2005 by jpr
+   gdcmDocument.cxx
+   Should avoid some troubles with 'no length' SQItems within 'true length'
+   Sequences.
+   Thx to Loic Boussel for providing data to fix the bug.
+
+Sun Jul 3 14:47:23 2005 by jpr 
+   gdcmSQItem.cxx
+   Enh warning message
+
+Fri Jul 1 13:25:51 2005 by jpr
+   gdcmPixelReadConvert.cxx
+   Initialize RLEInfo and JPEGInfo to 0 a avoid further problems
+   (e.g. PrintFile on a DICOMDIR document)
+
+Thu Jun 30 16:49:02 2005 by jpr
+   gdcmFile.cxx
+   Enhance gdcm::File::IsReable() heuristics to be able to process some Loic
+   Boussel's Hall of Shame Dicom images
+
+Wed Jun 29 17:58:33 2005 by jpr
+   gdcmDocument.cxx
+   Add the NO_SHADOWSEQ load mode
+
+2005-06-26 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+    * Quite a few new dictionaries were added in gdcm. The file:
+      gdcm/Dict/README should always explain were the info was found
+      (in case of double check). Also some dict are still only
+      express as 'template' (they contain 'xx'), therefore
+      a python script should be run first to generate a full dict.
+      In the longer term this python script should be replaced by
+      a cmake script.
+
+2005-06-25 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * dicomV3.dic is deprecated in favor of gdcm.dic
+     There is now a dictionary per family:
+     - dicomV3.dic -> DICOM V3
+     - Papyrus.dic -> Papyrus
+     - NIH.dic     -> tags that were never allowed in the main standard
+
+Fri Jun 24 12:50:20 2005 CEST by jpr
+   gdcmFile.cxx
+   Pixel Spacing related problems : update comments.
+   Thx to D. Clunie for providing data to check the code
+
+Fri Jun 24 12:55:58 2005 by jpr
+   Summer nights are really too hot to sleep.
+   Coding style : kosherization of all the 'if's (300 amongst 900 were haram)
+
+Thu Jun 23 11:20:23 2005 by jpr
+   gdcmDocument.cxx
+   Extend warning message, for debugging purpose
+
+Wed Jun 22 10:11:23 2005 by jpr
+   gdcmFile.cxx
+   Coding Style
+
+Wed Jun 22 10:00:29 2005  by jpr
+   gdcmPixelReadConvert.cxx
+   Fix misstyping, while removing spurious \t characters
+
+Wed Jun 22 09:52:32 2005 by jpr
+   gdcmPixelReadConvert.cxx
+   Some constructors (at least one ...) use BitsAllocated =! BitsStored for
+   negative Pixels.
+   That break at lot of viewers ...
+   We now *propagate the sign bit* upon the unused ones, better than masking them
+   out.
+   Thx to Luca Picello for profiding data to fix the bug
+
+Wed Jun 22 09:53:52 2005 by jpr
+   gdcmFileHelper.cxx
+   gdcm images are now "GDCM 1.1" built.
+
+Mon Jun 20 19:10:17 2005 by jpr
+   gdcmFileHelper.cxx
+   Avoid re writing Palette Color Lookup Table UID when Palette Color is removed
+
+Mon Jun 20 17:58:53 2005 by jpr
+   gdcmDocument.cxx
+   Preventive bug fix for LUT Data.
+   I said : LUT Date, *not* Palette Color
+
+Sun Jun 19 17:57:29 2005 by jpr
+   gdcmDocumentcxx
+   To avoid warnings at compile time
+
+Fri Jun 17 14:27:52 2005 by jpr
+   gdcmRLEFrames.cxx
+   Try to solve RLE pb
+
+Fri Jun 17 14:36:07 2005 by jpr
+   gdcmDocument.cxx
+   Add comments
+
+Fri Jun 17 14:35:00 2005 by jpr
+   gdcmFileHelper.cxx
+   Add some accessors for debugging purpose
+
+Tue Jun 14 15:56:41 2005 by jpr
+   gdcmPixelReadConvert.cxx
+   Now gdcm deals with 16 bits per pixel images with 16 bits Palette colors
+   (3 * 65536 short int ...)
+   Nice fat header.
+   "Segmented Palettes" pb still pending, but I never saw any viewer dealing with it.
+
+Mon Jun 13 17:43:48 2005 by jpr
+   gdcmPixelReadConvert.cxx
+   Some more oddities dealt with.
+   Doesn't work yet with 65536 entries 16 Bits LUT (?!?), with 16 bits pixels.
+   Still looking for accurate info on the web about it
+
+Fri Jun 10 16:05:38 2005 by jpr
+   gdcmDocument.cxx
+   Bug fix in Load method.
+   Thx to Benoit for providing fix.
+2005-06-08 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmUtil.cxx : change call to Util::Format to sprintf because of 
+     lantency with the Util::Format function
+
+Tue Jun 7 15:48:35 2005 by jpr
+   gdcmUtil.cxx
+   The highy time consuming method GetMacAdress is now called just once
+
+Tue Jun 7 11:58:29 2005 by jpr
+   gdcmDicomDirElement.cxx
+   Use TranslateToKey better than Format
+
+Tue Jun 7 12:07:20 by jpr
+   gdcmDictEntry.cxx
+   Remove some spurious calls to Format
+   // according to 'Purify', TranslateToKey is one of the most
+   // time consuming methods.
+   // Let's try to shorten it !
+
+Mon Jun 6 14:37:58 2005
+   class ArgMgr (for Arguments Manager) is designed for
+       command line arguments management
+       (to make programmer's live easier)
+       (could be used for any kind of 'command line program')
+
+2005-06-07 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Adding users file in CVSROOT for mail blaming 
+
+2005-06-04 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Adding potential support for JPEG-LS DICOM files.
+
+Fri Jun 3 18:05:23 2005 by jpr
+   gdcmDocument.cxx
+   Fix VR processing, to be CP-288 conform.
+   Now we can parse any kind of DICOM SR.
+
+Fri Jun 3 11:05:15 2005 by jpr
+   gdcmDocument.h
+   Doxygenation
+
+Thu Jun 2 15:42:18 2005 by jpr
+  gdcmDocument.cxx
+   Add warning about Load Mode
+
+Thu Jun 2 16:20:14 2005 by jpr
+   gdcmFile.cxx
+   Harden gdcm::File::IsReadable(), in order not to be confused any longer
+   by lost of Pixel Element
+
+Fri May 27 12:51:00 2005 by jpr
+   gdcmFileHelper.cxx
+   To avoid pushing out twice the meta elements, wile trying to write 'ACR-NEMA-
+   style.
+   And avoid some memry leaks -hope so-
+
+Wed May 25 14:54:17 2005 by jpr
+   gdcmDocument.cxx
+   Should avoid some memory leaks
+
+2005-05-22 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Adding potential support for mpeg and jpeg2000 through two new lin
+    - JasPer for JPEG2000
+    - libmpeg2 from the MPEG consortium
+    Also adding intial work to use this lib.
+
+Fri May 20 10:27:55 2005 by jpr
+   gdcmFileHelper.cxx
+   To avoid warning.
+   (this time, it's wasn't dangerous at run time)
+
+Thu May 19 17:31:21 2005 by jpr
+   gdcmFileHelper.cxx
+   FIX possible troubles when checking
+     'Hight Bit Position' vs 'Bits Allocated' and 'Bits Stored'
+   Thx to Mathieu for reporting bug
+
+Wed May 18 12:12:07 2005 by jpr
+   gdcmDocument.cxx
+   Fix : now dcm deals with 'No preamble', Big Endian Explicit VR group 0002.
+   Thx to Dennis Hu for providing a sample image to fix the bug.
+
+Tue May 17 14:44:09 2005 by jpr
+   gdcmFile.cxx
+   ENH : According to David Clunie's advice, we check now 'Imager Pixel Spacing'
+      before 'Pixel Spacing', when we want to get X or Y Spacing.
+
+Tue May 17 19:10:49 2005 by jpr
+   gdcmFileHelper.cxx
+   ENH : Now, FileHelper::CheckMandatoryElements() makes some consistency checking,
+         at LTTG (Least Time To Go)
+         around Bits Allocated, Bits Stored, High Bit Position,
+         to avoid unaware user to mess up the stuff.
+
+Tue May 3 11:43:04 2005 by jpr
+   gdcmDicomDir.h, .cxx
+   Load returns now a bool (allow user not to call IsReadable() )
+
+Tue May 3 11:51:06 2005by jpr
+   gdcmFileHelper.cxx
+   Now the gdcm::File remains unimpaired after writting, in any case
+
+Fri Apr 29 17:10:55 2005by jpr
+   gdcmDocument.cxx
+   Don't abort the prog when File not open
+
+Wed Apr 27 12:00:35 2005 by jpr
+   gdcmFile.cxx
+   Removal of now useless lut-related stuff
+
+Wed Apr 27 11:52:27 2005 by jpr
+   gdcmFile.cxx
+   Pb of 'Bits Allocated = 12' is now dealt with in
+   FileHelper::CheckMandatoryElements, no longer in File::Write.
+   Thx to Mathieu for reporting bug.
+
+2005-04-26 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Testing/TestAllReadCompareDicom.cxx : update the test printed results and
+     description.
+
+Tue Apr 26 18:18:23 2005 by jpr
+   gdcmDocument.cxx
+   Should leave gdcm::Document constructor in a much quicker
+   and much cleaner way when anything wrong occurs.
+
+Tue Apr 26 18:25:49 2005 by jpr
+   gdcmPixelReadConvert.cxx
+   Prepare MPEG Dicom encapsulated processing (within a loooong future)
+
+Fri Apr 22 14:59:58 2005 by jpr
+   gdcmDocument.cxx
+   Modify Print() output
+
+Fri Apr 22 15:37:57 2005  by jpr
+   gdcmTS.cxx
+   Prepare (future) MPEG integration
+
+Thu Apr 21 09:40:00 2005 by jpr
+   gdcmTS.cxx
+   Taking into account Dicom MPEG
+
+2005-04-20 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * FIX : Numerical exception on borland (cannot divide by 0, doh !)
+         But this is a case where we should really signify the user there is
+         few chance the serie is really a serie...
+
+2005-04-20 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * FIX : on X, the python part is correctly installed. All files are
+     installed in gdcm sub-directory
+
+Tue Apr 19 11:58:19 2005 by jpr
+   gdcmDocEntry
+   Should suppress some warnings from Borland compiler
+
+2005-04-19 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Builder/ : add something to facilitate the RPM creation of gdcm
+
+2005-04-15 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Fix gdcmDirList::IsDirectory. Apparently borland did not like the ending
+     '/'
+   * Also fix compilation on gcc 3.3.5 does not have ios::failure either ...
+
+Thu Apr 14 16:26:19 2005 by jpr
+   gdcmDicomDir.h, .cxx
+   Now, user can ask gdcm::DicomDir to skip SeqEntries or shadow groups, when
+   possible :
+     // Old style (still available) :
+     dcmdir = new gdcm::DicomDir(dirName, true);
+
+    // new style (user is allowed no to load Sequences an/or Shadow Groups)
+    dcmdir = new gdcm::DicomDir( );
+    dcmdir->SetParseDir(true);
+    dcmdir->SetLoadMode(NO_SEQ | NO_SHADOW);
+    dcmdir->Load(dirName);
+
+2005-04-11 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * vtk/vtkGdcmWriter fix bug when writing spacing. The Y spacing comes first
+     then the X spacing.
+    * Fix compilation on gcc 2.96 (which does not have ios::failure)
+
+Mon Apr 4 17:15:24 2005 by jpr
+   gdcmFileHelper.cxx
+   Fix stupid bug when writting ACR-NEMA image from 'ACR-LibIDO' one.
+
+2005-04-05 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDictGroupName.[h|cxx] : add a correlation between a group (number)
+     and it's representation name (for the NIH)
+
+2005-03-31 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmPixelReadConvert.cxx : problems of around of double to uint8, when
+     conversion of YBR to RGB pixels. So, now, the conversion is made using 
+     integers only
+
+2005-03-30 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Testing/TestAllReadCompareDicom.cxx : now use test files (invented file
+     format) to replace 'at-run' dicom files generated by the 
+     TestAllReadCompareDicom test
+
+Tue Mar 22 12:29:37 2005 by jpr
+   gdcmDocument.cxx
+   * FIX : element 0x0000 of shadow groups is now force to a ValEntry, 
+     and it's VR is forced to UL
+   * ENH : user id now allowed to tell he doesn't want to deal with Sequences
+      and/or with Shadow groups
+      use SetLoadMode (NO_SEQ | NO-SHADOW);
+
+Tue Mar 22 12:40:13 2005 by jpr
+   gdcmFileHelper.cxx
+   *FIX Restore pushed out elements
+
+Fri Mar 11 12:08:31 2005 by jpr
+   gdcmDocEntry.cxx
+   Remove spurious #define MAX_SIZE_PRINT_ELEMENT_VALUE
+
+Fri Mar 11 12:12:13 2005 by jpr
+   gdcmFile.cxx
+   Final removal of gdcmFileHelper::InitializeDefaultFile();
+
+Wed Mar 9 20:29:38 2005 by jpr
+   gdcmDicomDir.h, .cxx
+   Add Anonymize method (not yet fully checked)
+
+2005-03-07 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFileHelper.cxx : remove memory leaks and bugs when writing files
+
+Wed Mar 2 18:18:32 2005by jpr
+   gdcmFile.cxx
+   Fix gdcm::FileHelper::CheckMandatoryElements() to take into account David
+   Clunie's remarks.
+
+2005-02-22 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFileHelper.cxx : JPR bad personal choices fix
+
+Mon Feb 21 18:45:41 2005 by jpr
+   gdcmFileHelper.cxx
+   * Replace method CheckMetaElements by CheckManadatoryElements
+     To deal with the pb of UID's, and with Type 1 an Type 2 Entries
+     (probabely some stuff still missing)
+   * We shall have to decide the way we proceed to allow user 'freeze' Serie UID
+      between a given call and the next one (to add images to a Serie he just
+      created)
+  * We shall have to decide the way we proceed to allow user 'freeze' Study UID
+      between a given call and the next one, or to reuse an already existing
+      Study UID (i he wants to add his own Series to an already existing Study)
+
+Thu Feb 17 17:18:33 2005 by jpr
+   gdcmFile.cxx
+   To avoid further pb, Initialize defaults now Photochromatic Interpretation to
+   MONOCHROME2 (low values = dark), better than MONOCHRONE1.
+   Thx to Benoit for reporting bug
+
+Thu Feb 17 11:56:20 2005 by jpr
+   gdcmUtil.cxx
+   Prepare FileMetaInformationVersion (group 0002) management
+
+Thu Feb 17 12:02:47 2005 by jpr
+   gdcmFile.cxx
+   Group 0002 management
+
+Thu Feb 17 12:03:32 2005 by jpr
+   gdcmDocEntryArchive.cxx
+   Fix comments
+
+Wed Feb 16 11:19:19 2005 CET by jpr
+   gdcmPixelReadConvert.cxx
+   Taking into account MONOCHROME1 + Signed Pixels (?!)
+
+Tue Feb 15 19:12:34 2005  by jpr
+   gdcmFile.cxx
+   Taking into account the difference between MONOCHROME1 (low values = bright)
+   and MONOCHROME2 (low values = dark)
+
+Mon Feb 14 11:45:04 2005by jpr
+   gdcmDocument.cxx
+   Remove some useless mask operations, to save CPU time
+
+Mon Feb 14 15:51:10 2005 by jpr
+   gdcmUtil.cxx
+   *never* forget to re-compile just *before* committing!
+
+Mon Feb 14 15:34:27 2005 by jpr
+   gdcmUtil.cxx
+   First commit on the post 1.0 (Version? / Tag? / Branch?) :
+   Fix Doxygen warnings
+
+Mon Feb 14 11:45:47 2005 by jpr
+   gdcmValEntry.cxx
+   remove useless comments
+
+2005-02-11 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Testing/TestMAkeIcon.cxx : complete the test
+
+2005-02-10 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Testing/TestWriteSimple.cxx, TestSequence.cxx : fix memory leaks
+
+Fri Feb 11 16:22:18 2005 by jpr
+   gdcmDocEntrySet.cxx
+   Typo, comments, doxygenation
+
+Thu Feb 10 11:55:26 2005 by jpr
+   gdcmFile.cxx
+   AnonymizeNoLoad improvement
+
+Thu Feb 10 10:07:19 2005 by jpr
+   gdcmFile.cxx
+   Duplicate Matthieu's hack to prevent bombing in Anonymize
+
+Thu Feb 10 12:20:34 2005by jpr
+   gdcmDocEntrySrt.cxx
+   The following gdcm::DocEntrySet methods, no re-definable is child classes are no
+   longer virtual
+    virtual ValEntry *GetValEntry(uint16_t group, uint16_t elem);
+    virtual BinEntry *GetBinEntry(uint16_t group, uint16_t elem);
+    virtual SeqEntry *GetSeqEntry(uint16_t group, uint16_t elem);
+    virtual bool SetValEntry(std::string const &content,
+    virtual bool SetBinEntry(uint8_t *content, int lgth,
+    virtual bool SetValEntry(std::string const &content, ValEntry *entry);
+    virtual bool SetBinEntry(uint8_t *content, int lgth, BinEntry *entry);
+    virtual ValEntry *InsertValEntry(std::string const &value,
+    virtual BinEntry *InsertBinEntry(uint8_t *binArea, int lgth,
+    virtual SeqEntry *InsertSeqEntry(uint16_t group, uint16_t elem);
+
+2005-02-09 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFileHelper.[h|cxx] : now correctly set the VR of the datas when 
+     writting the file
+
+2005-02-09 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/VTKTestWriteSeq.cxx : add a VTK test to write sequences
+
+2005-02-09 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/ : accelerate tests (it's not very significant accelerations).
+     Remove TestCopyDicom that is redundant with TestCopyRescaleDicom
+
+Mon Feb 7 15:48:34 2005 by jpr
+   gdcmDicomDir.h, .cxx
+   Add some commented out lines to prepare future version of 'Full DICOMDIR' stuff
+
+
+2005-02-07 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Testing/TestSequence.cxx : add test for sequences of images... test that
+     we have the same serie or the same study UID
+
+2005-02-07 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * gdcmPython/gdcm.i : bug fix. Now string are correctly converted in python
+     string type
+   * src/gdcmDict.h : remove commented code
+   * src/gdcmDocument.cxx : initialize values
+   * src/gdcmFile.cxx : bug fix when reading values
+   * gdcmPython/demo/ : change file names. Remove useless files
+
+Sun Feb 6 15:31:09 2005 by jpr
+   gdcmDicomDirStudy.h
+   Update comments for DicomDir stuff
+
+Sun Feb 6 15:39:35 2005 by jpr
+   gdcmDocument.cxx
+   * Add method File::AnonymizeNoLoad, to allow anomymizing files
+           even when the pixels are not gdcm Readable
+    * Add methods File::AddAnonymizeElement and File::ClearAnonymizeList
+            to allow user to choose the elements whose value
+            he wants to white out / replace
+
+2005-02-04 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFile.cxx : remove the default array of initialization.
+     The static array contained pointers to non-static values (comming from
+     strings). To have coherences, when creating files, these values can't be
+     static. So, the array can't be static, too ! To simplify, the array have
+     been replaced by repeted lines to insert values in the File
+
+Fri Feb 4 15:49:01 2005 by jpr
+   gdcmDocEntry.cxx
+   * Add GetFirstValEntry + GetNextValEntry, for Python users
+   * Some more Doxygenation + typo fixing
+
+2005-02-03 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmBinEntry.cxx : bug fix for BIG_ENDIAN part when writing the content
+   * gdcmPython/gdcm.i : rename gdcmHeader to gdcmHelper
+
+Thu Feb 3 18:12:46 2005 by jpr
+   gdcmPixelReadConvert.cxx
+   Fix Doxygen warning
+
+2005-02-02 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * FIX SQItem::AddEntry inserts now *in the right place* any Entry
+              (Dicom Element) into the Sequence Item
+
+2005-01-31 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/*.cxx : first parss to normalize file organisation
+
+2005-01-31 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDirList.[h|cxx] : add method to find a directory
+   * Test/TestAllReadCompareDicom.cxx : bug fix under Windows
+
+2005-01-31 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Finish cleaning up my JPEG mess. Should be ok now.
+   * Getting toward a RLE very similar to JPEG. Every RLE stuff is now self
+      contained within the RLE* class(doh!)
+
+2005-01-30 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * SerieHeader::SetDirectory() allow recursive exploration of the Directory
+   * SerieHeader::AddFileName() creates as many Coherent Files lists 
+             (same Serie UID) as it founds different Serie UID 
+              amongst the files instead of discarting any file 
+             that doesn't match with the first one he found.
+    * SerieHeader::OrderGdcmFileList has now one parameter : 
+               the Coherent Files list the user wants to sort
+   * SerieHeader::GetFirstCoherentFileList()  |
+   * SerieHeader::GetLastCoherentFileList()   | allow to parse 
+               the set of Coherent Files lists 
+   * const SerieHeader::GdcmFileList &GetGdcmFileList() is kept, for backwards
+               compatibility (it returns the *first* Coherent Files list, 
+               since there was only one before)
+   * Test/TestSerieHeader gets gdcmData as a default root directory
+  
+2005-01-28 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Remove friend between DocEntry and File classes
+   * Remove friend between PixelReadConverter and RLEFramesInfo, 
+     JPEGFragmentsInfo
+
+2005-01-28 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFile.cxx, gdcmDocument.cxx : fix the bug on the group|element
+     0002|0000. The value was incorrect.
+
+2005-01-28 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * vtk/vtkGdcmWriter.[h|cxx] : add the gestion of UID
+
+2005-01-28 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmUtil.cxx : compilation fix on Win32
+   * src/gdcmUtil.[h|cxx] : Set the default GDCM UID in a static constant
+     variable, to be easy found. Add methods to change the default UID.
+     Amelioration of the CreateUniqueUID to use the correct default UID.
+   * src/gdcmFile.cxx : correct use of the CreateUniqueUID method to create
+     a new file
+
+2005-01-28 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/TestVR.cxx : fix memory leaks
+
+2005-01-27 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Rewrite the base 256 to base 10 conversion, using string operation only.
+     This allows us to get rid of the problematic 64bits integer type (does not
+     always exist on target platform).
+
+2005-01-27 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * Add construct and destructor to class gdcm::Debug to close the debug file
+          automatically
+   * Don't let uset to open twice the same file
+   * gdcm has now an official UID prefix,
+          supplied by http://www.medicalconnections.co.uk
+          1.2.826.0.1.3680043.2.1143
+          (Thx to Mathieu for providing URL)
+   * Add a forty-entries private Dicom Dictionary (Philips MR Intera)
+         to be able to perform some more tests
+   * gdcm::ContentEntry : Contructors and Destructor are now protected,
+         in order to be sure no user will try to use them.
+         (at user level, only the children classes are meaningfull)
+
+2005-01-26 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * move RLEInfo & JPEGInfo from Document to File
+
+2005-01-26 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * FIX : remove so many friend between classes
+
+2005-01-25 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocEntrySet.cxx : Bug fix when getting the value
+   * src/gdcmContentEntry.[h|cxx], gdcmValEntry.cxx : amelioration of code
+
+2005-01-25 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   In order to avoid missbehaviour :
+   . gdcm::DocEntry is now specialized in
+     - gdcm::SeqEntry (Dicom Sequence) as opposed to :
+     - gdcm::ContentEntry (Dicom entry with a 'content')
+   . gdcm::ContentEntry is specialized in
+     - gdcm::ValEntry (Dicom entry with a std::string representable value, i.e.
+       characters value, or integers)
+     - gdcm::BinEntry (Dicom entry with a non strig representable value
+   (user hasn't any longer to thing about the precedence of his dynamic_casts)
+
+2005-01-25 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/VTKTest*.cxx : bug fix under linux
+
+2005-01-25 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/ : rename some methods on Entry (SetXxx, InsertXxx) to have a better
+     use with python. Some methods are moved from Document to ElementSet or
+     DocEntrySet. The equivalent methods to ElementSet have been added to 
+     SQItem and are virtual in DocEntrySet. Methods that may have the same code
+     in SQItem and ElementSet is directly placed in DocEntrySet
+
+2005-01-25 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/VTKTest*.cxx : remove the show variable in each test method because
+     it's useless (the viewer variable replace this variable)
+
+2005-01-25 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocument.cxx : bug fix on potential memory leak
+   * src/gdcmSQItem.cxx : initialize the SQItemNumber value in the constructor
+   * src/gdcmSQItem.[h|cxx], gdcmElementSet.[h|cxx], gdcmDicomDir*.[h|cxx] : 
+     Add ClearXxx methods to remove all the content of the list or map
+   * gdcmDocEntrySet.h : add GetFirst/NextEntry in pure virtual
+
+2005-01-25 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * methods ReplaceOrCreate renamed as Insert
+     (nobody will be any longer confused by 'CreateOrReplace')
+  
+2005-01-24 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Grealty simplify the JPEg decompression, no need to differenciate based on 
+     the JPEG possible type (with/without fragment, with/without multiple frame). 
+     Everything is done throught the JPEG IO Suspension mechanism in IJG
+
+2005-01-24 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * Stage 3 of normalization :
+     in order to avoid any missunderstanding while reading method names :
+     - All the methods xxxEntry now deal with dicom Entries
+     - Methods GetEntry splitted into
+        GetEntryValue
+        GetEntryBinArea
+     - Method SetEntry renamed as SetEntryValue
+     - Method SetEntryBinArea let as it was
+
+2005-01-24 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+    - Add empty nutshell for JPEG-LS (JPG-LS in NOT jpeg 'lossless')
+    - Position correctly the entry points for JPEG2000 and JPEG-LS
+      (Now Fragments info is get from the file, even for JPEG2000 and JPEG-LS)
+
+2005-01-22 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDicomDirElement.h, gdcmDict.h : rename AddNewXxx methods to AddXxx.
+   * src/gdcmDict.h : rename GetDictEntry moethod to GetEntry, to be coherent 
+     with other method names
+   * gdcmPython/gdcm.i : bug fix. Add the typemaps for the TagName type
+   * Test/TestDicomDirElement.cxx : add new test
+
+2005-01-22 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Finish the CreateUniqueUID stuff. Seems to compiled/runs on every
+     plateforms ITK support. Had some troubles with uint64_t on Win32, go to
+     http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_langref_data_type_ranges.asp
+     for more info. Basically you can not used 'unsigned' __int8 in an ostream.
+     So can't you use __int64 in ostream at all.
+
+2005-01-22 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * bug fix for compilation on MSVC6
+   * gdcmPython/gdcm.i : rename of classes missed
+
+2005-01-21 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * Stage 2 of names normalization :
+     - A gdcm::Document is now either a gdcm::DicomDir or a gdcm::File
+       (easy to understand ...)
+     - gdcm::FileHelper replaces old class gdcm::File
+
+2005-01-20 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * gdcmDicomDirElement.[h|cxx] : change the AddEntry method. Now, it gets a
+     type and not a string. So, there remove problems on the format of the
+     string.
+
+2005-01-20 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * Add Example/TestPapyrus.cxx
+     - reads a Papyrus file (gdcm::Header compliant),
+     - gets the pixels of all the images, using low level iterators
+     - writes an multiframes Dicom image.
+   (Just to show it's *possible* to do that)
+    Uses SQItems accessors (we could use it as a 'Test' program, to improve test
+    coverage ...)
+
+2005-01-20 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDicomDirObject.h : set the FillObject method in protected.
+     Thus, DicomDirXXX are created with a flad that indicates if the created
+     object is empty or not (when not empty, the DicomDirElement is used to
+     fill the object)
+
+2005-01-20 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDicomDir.cxx : simplify the NewPatient method, like made in
+     gdcm::DicomDirPatient, gdcm::DicomDirStudy, gdcm::DicomDirSerie
+
+2005-01-20 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmSQItem[h|cxx] : rename some methods to have coherent names
+
+2005-01-20 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDicomDir*.[h|cxx] : rename methods to be logik in their name.
+     Remove all access to the hash-tables or lists in the objects.
+
+2005-01-20 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDebug.h : remove the Debug test in the gdcmErrorMacro
+   * src/gdcmDocument.[h|cxx] : rename the Initialise method to Initialize, to
+     be complient with all the gdcm source code
+
+2005-01-19 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocEntry.h : DocEntry is now secure. User can't change the
+     DictEntry or the VR.
+
+2005-01-19 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * gdcmPython/ : change GDCM_DATA_PATH to GDCM_DATA_ROOT to be complient with
+     all in gdcm
+
+2005-01-19 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/ : rename VTK tests to have a best name for the tests
+   * gdcmPython/demo/*.py.in : Change the InitTraversal/GetNextEntry use to
+     GetFirstEntry/GetNextEntry use
+
+2005-01-18 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * In SerieHeader::ImagePositionPatientOrdering()
+     // a Dicom 'Serie' may contain scout views
+     // and images may have differents directions.
+     // -> More than one may have the same 'pos'
+     // Sorting has then NO meaning !
+     Thx to Eduardo Davila for reporting bug.
+
+2005-01-18 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/ShowDicom.cxx, ShowDicomSeq.cxx, TestWriteWithVTK.cxx : change the
+     test. Now it's on image content and not on the resulting visualisation...
+     might solve the problem on linux when using the OpenGL drivers
+
+2005-01-18 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * ENH for DicomDir, DicomDirPatient, DicomDirStudy, 
+             DicomDirSerie, DicomDirImage
+             Dict, DictSet classes :
+         -add method GetFirstEntry to replace call to InitTraversal+GetNextEntry
+         -remove InitTraversal method.
+   * UPD Test programs + Example programs
+
+2005-01-18 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * remove useless and never updated keyword \ingroup         
+   * Solve pb when structure (list, map, ...) is empty.
+     Thx to Benoit for reporting bug
+
+2005-01-18 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * Taking into account of 'Transfer Syntax' value
+       (for 'true' Dicom V3 files, the 'ACR-NEMA' heuristics sometimes gives
+         unaccurate result)
+
+2005-01-17 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmUtil.cxx : bug fix to find the Windows MAC address. Now, there
+     is no memory access violation
+   * gdcmPython/demo : add python demos using VTK
+
+2005-01-16 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+    * FIX 'Dictionnary' is now spelt 'Dictionary'
+          'wether' is now spelt 'whether'
+          'archieve' is now spelt 'archive'   ;-)
+
+2005-01-15 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+    * ADD DicomDir, DicomDirPatient, DicomDirStudy, DicomDirSerie, DicomDirImage
+          related methods, in order not to expose internal mechanisms
+        InitTraversal();
+        GetNextEntry();
+    * REM methods that exposed internal mechanisms :
+        DicomDir::GetDicomDirPatients()
+        DicomDirPatient::GetDicomDirStudies()
+        DicomDirStudy::GetDicomDirSeries()
+        DicomDirSerie::GetDicomDirImages()
+    * UPD Test programs :
+        makeDicomDir.cxx
+        BuildUpDicomDir.cxx
+        TestDicomDir.cxx
+     * UPD Example program
+        PrintDicomDir.cxx
+    * ADD DictSet methods
+        InitTraversal()
+        GetNextEntry()
+
+2005-01-15 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Removed the Print/indent/default parameter mess. There is absolutely no
+    reason to have to methods, moreover with the second taking the ostream as
+    *SECOND* parameter. This was clearly a bad hack to get things compile.
+
+2005-01-15 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Complete rewrite of the GetMacAddress code. Now the code is *much*
+    smaller (no more MacOSX specific crap). A lot more POSIX oriented.
+    Unfortunately the main code does not work on SunOS, thus provide a specific
+    code for this platform only (and Win32 of course). Since this seems to be
+    working, change CreateUniqueUID to use GetMACAddress instead of the
+    problematic GctestetIPAddress
+
+2005-01-14 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Unfortunately to be able to test gdcmDirList I had to break the API
+     a little. Now the class is not a std::list anymore but has a member
+     std::vector (more ITK compatible). Allow unit testing on Win32 and
+     shared libs.
+
+2005-01-14 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Update SerieHeader to take into account a Serie Instance UID to properly
+     sort DICOM files
+
+2005-01-13 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * ENH - Comment out Mathieu's (dangerous) Super Hack
+         for dealing with BIGENDIAN processors
+         - Move equivalent stuff to BinEntry::WriteContent
+         When necessary, 16 Bits Pixels are swapped in a small buffer
+         and then written. This avoid allocating a huge buffer, in
+         PixelWriteConvertor, and avoid modifying the Pixel Area.
+         Note :
+         Probabely, the same operation will have to be done when we want 
+         to write image with Big Endian Transfert Syntax, 
+         and we are working on Little Endian Processor
+                  
+2005-01-14 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocument.[h|cxx] : comment all methods concerning a flat hash
+     table.
+   * src/gdcmElementSet.[h|cxx] : rename Initialize into InitTraversal
+   * src/gdcmDict.[h|cxx] : add InitTraversal/getNextEntry methods to parse
+     all the dict content.
+   * src/gdcmDictEntry.cxx : add a carriage return at the end of the DictEntry
+     print
+   * Test/TestDict.cxx : add a new test for the dict classes
+
+2005-01-13 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * src/gdcmDebug.h : Adding an option to redirect debug stream to a 
+                       file. Debug is yanked if compiled with NDEBUG
+
+2005-01-13 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDictSet.h : set the default output to the os variable
+   * src/gdcmDictEntry.[h|cxx] : add the Print method
+   * gdcmPython/demo/ : add a new test
+
+2005-01-13 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * merging of Test/PrintDicomDir and Test/TestDicomDir
+   * removal of now redundant Test/PrintDicomDir
+   * enhancement of Example/PrintDicomDir
+
+2005-01-13 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Now, python test might work on systems
+   * Add the PrintDicomDir test
+
+2005-01-13 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * FIX : First entry following group 0002 was lost for
+           Explicit Big Endian Transfer Syntax files
+          (group and elem not swaped)
+   
+2005-01-12 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * FIX : Old quick and dirty 'optimistic' heuristic to deal with
+           Big Endian Transfer Syntax supposed the group following 0002
+           begins always by element 0000 (element 0000 is *optional*)
+           To avoid further troubles, let's be pessimistic, and use
+           Document::HandleOutOfGroup0002() method 
+    * FIX : comparison between GDCM_NOTLOADED and Transfer Syntax
+              (related pb not yet solved)
+
+2005-01-12 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Bug fix for the python part use
+   * Now, PrintHeader.py pass... but outside the ctest use. shit !
+
+2005-01-12 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * gdcmPython/gdcm.i : bug fix when compiling with MSCV
+
+2005-01-11 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Untangle TransferSynatx from gdcm::Document. Now Document only manipulate
+     a string and should ask the global TS dict what are the propreties of 
+     the transfer syntax
+
+2005-01-11 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * Replace confusing name SwitchSwapToBigEndian name by SwitchByteSwapCode
+   * Add the Document::HandleOutOfGroup0002(uint16_t group) method
+       to swap the Swap Code, at parsing time, when we come out of group 0002
+       and Transfer Syntax is Big Endian
+       We should be able to read now 'true DICOM" Big Endian coded images
+    * Add optional run time SetDebugOn (last param) for PrintHeader, PrintFile
+    * Replace the french 'Transfert Syntax' by the english 'Transfer Syntax'
+
+2005-01-10 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Hopefully fix the bug on MacOSX and static global initialization.
+   This is the only -minor- patch I found that both please MacOSX and VS6.
+   Other patch would be to declare a const std::string & GDCM_UNFOUND() instead,
+   but this would require a lot of change. Another approach would be that Global
+   create those string and GDCM_UNFOUND becomes a pointer to a string (which
+   gdcm::Global would destroy at exit).
+
+2005-01-08 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Fix bug on MacOSX with static initialization in a multy threaded
+    environment. static const string in a header file used to be ill
+    initialized provoquing the freeze of any tests. patch should solve this
+    issue.
+
+2005-01-08 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * According to Benoit's suggestion, and without any objection from anybody
+      - methods SetxxxByNumber and GetxxxByNumber renamed as Setxxx and Getxxx
+      - methods Dict::Print() and Dict::PrintByKey() merged into Dict::Print()
+      - method gdcmDicomDirObject::GetEntry() renamed as 
+         gdcmDicomDirObject::GetEntryHT() to avoid confusion (and compile error)
+
+2005-01-07 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Now gdcm::Debug is clearly a copy/paste of VTK approach. You can manipulate
+     you debug/warning message just as c++ streams which make them very convinient
+     to use. Once this is stabilize I will change the ostringstrem to be
+     redirected to a file (ofstream).
+   * Properly support C99 extension: __FUNCTION__ which allow us to display
+     the name of the function call (GNUC also allow __PRETTY_FUNCTION__ for c++)
+
+2005-01-07 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * Removal of useless and dangerous methods :
+         GetEntryByName, GetEntryVRByName, GetDocEntryByName, SetEntryByName
+         GetDocEntryByName, GetEntryByName, GetDictEntryByName
+   * Removal of usless methods :
+         Dict::PrintByName, Dict::GetDictEntryByName
+   * Commenting out of probabely useless methods :
+         Dict::GetDictEntryNames()
+         Dict::GetDictEntryNamesByCategory()
+         DictSet::GetPubDictEntryNames()
+         DictSet::GetPubDictEntryNamesByCategory()         
+   * ENH : New Dicom Dictionary (with Value Multiplicity) is now used    
+   * ENH : Use dicomTS.dic as described in 2004 version   
+   * ENH : Removal out of the Dicom Dictionary of non dicom 'fourth' field
+           Add         to the Dicom Dictionary of Dicom 'Value Multiplicity' field
+           Add Accessors on VM (Value Multiplicity), and VM related methods           
+   * ADD : Add a list of 'Dicom Attribute types', as found in
+           http://medical.nema.org/dicom/2004/04_15PU.PDF
+                      Unused till now...           
+   * ADD : Add dicomGroupNameAbbreviations.dic
+           should be used to write a method to replace the former
+           Dict::GetDictEntryNamesByCategory()
+
+2005-01-07 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocEntry.[h|cxx] : now the ReadLength is the length of the data
+     to read in the file... and only it ! Length is the efective length of the
+     data in the DocEntry structure
+
+2005-01-07 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Change the gdcmDebug approach. Remov the global static debug 'dbg'.
+     And now use a static function call instead, with a global variable. i
+     This is much closer to the VTK approach. Hopefully should be bulletproof
+     and easier to use...hopefully
+
+2005-01-06 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Adding GetMACAddres very alpha for now. This is tricky to be cross plateform.
+
+2005-01-06 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocument.[h|cxx] : remove all copy of DocEntry when parsing a file
+
+2005-01-06 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocEntrySet.[h|cxx], gdcmDocument.[h|cxx] : amelioration of
+     ValEntry, BinEntry, SeqEntry creation or replace
+
+2005-01-06 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDictEntry.h : now, the IsVRUnknown is correct
+   * src/gdcmDocument.[h|cxx] : simplify the search of VR value when parsing
+     a file
+   * src/gdcmDocEntrySet.cxx : now the created DocEntry without values is good
+     when specifying the VR
+   * src/gdcmVR.[h|cxx] : add usefull method to test the validity of a VR
+   * src/gdcmDocEntry.cxx : amelioration of print
+
+2005-01-05 Jean-Pierre Roux <jpr@creatis.univ-lyon1.fr>
+   * ADD : Add the method Util::IsCurrentProcessorBigEndian
+          (we'll need it for 'Explicit VR Big Endian' Transfert Syntax)
+   * ADD  Method Document::ComputeGroupLength
+   * ENH : now  parsing creates a Vitual DictEntry for Pixels Element,
+           in order to allow further VR modification by user
+   * REM : removal of once-called method File::WriteBase   
+           integration of its code in formerly one-line method File::Write
+
+2005-01-05 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmCommon.h : add the GDCM_UNKNOWN constant. This constant is to
+     replace the different values "??", "Unkn", "Unknown".
+   * src/gdcmDicomDirElement.h, gdcmDictEntry.h, gdcmDictSet.h,
+     gdcmDocEntry.cxx, gdcmDocEntrySet.[h|cxx], gdcmDocument.h, gdcmSQItem.cxx,
+     gdcmVR.cxx : use the GDCM_UNKNOWN constant.
+   * Appears a bug in gdcmDictEntry : IsVRUnknown always returns false... bad
+
+2004-12-16 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmBase.[h|cxx] : new base class. Contains the PrintLevel and an
+     empty Print Method
+   * Set the gdcm::Base class to some Printable classes
+
+2004-12-16 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFile.[h|cxx] : add the Print method
+   * src/gdcmPixelReadConvert.[h|cxx] : add the generalized Print method
+   * src/gdcmDocEntrySet.h : generalize the Print with the PrintLevel
+   * src/gdcmDocument.h : remove the PrintLevel informations
+   * Example/PrintFile.cxx : use the new gdcm::File::Print
+
+2004-12-16 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFile.cxx : Add the code of ReplaceOrCreateByNumber to not have
+     problems when compiling with the python wrapping
+
+2004-12-16 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFile.cxx : bug fix. Omitted a Push in the DocEntryArchive when
+     writting in ImplicitVR
+
+2004-12-12 Jean-Michel Rouet <jm.rouet@noos.fr>
+   * src/gdcmPixelReadConvert.[h|cxx], src/gdcmJpeg*.cxx : new handling of
+     JPEG decompression, especially when dicom frames are split into several
+     JPEG Fragments. This makes use of jpeg decompression from memory buffer.
+     This solves reading for example gdcm-JPEG-Lossless_Thoravision.dcm.
+
+2004-12-10 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmHeader.cxx : change the initialisation of default header.
+     Now, this header is readable by gdm, e-film, DicomWorks
+
+2004-12-10 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFile.[h|cxx], gdcmPixelReadConvert.[h|cxx] : change the API.
+     Rename Decompressed to Raw
+   * Use the API changes in gdcm::File.
+   * vtk/vtkGdcmWriter.[h|cxx] : add the possibility to write in other modes
+     Memory leaks fixed
+
+2004-12-10 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * vtk/vtkGdcmWriter.cxx, Example/WriteDicomSimple.cxx : add comments for
+     each added entry in the header. Replace the 'Planes' field by the 'Number
+     of Frames' field
+
+2004-12-09 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * vtk/vtkGdcmWriter.[h|cxx] : now can write stack of images.
+   * vtk/vtkWriteDicom.cxx : can write 2D stack or 3D image
+
+2004-12-09 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Example/WriteDicomSimple.cxx : example to write a dicom file from nothing.
+     At this time, this image isn't readable by e-film... waiting JPR help to
+     solve it.
+
+2004-12-09 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmPixelReadConvert.cxx : bug fix when would forcing load of a
+     DocEntry. Now use methods of the Document !
+
+2004-12-09 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/ShowDicomSeq.cxx : bug fix
+ 
+2004-12-08 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * vtk/vtkGdcmReader.[h|cxx] : bug fix. Plane order isn't inverted
+   * vtk/vtkGdcmWriter.[h|cxx] : correctly write images (the Y axis is inverted)
+   * Test/ShowDicomSeq.cxx : new test to verify the use of AddFileName method
+   * Test/ShowDicom.cxx, TestWriteWithVTK.cxx : set the threshold of regression
+     test to 0.0
+   * Test/TestCopyRescaleDicom.cxx : remove unused variable
+   * Test/CMakeLists.txt : add the creation of the gdcmDataSeqImages.h file
+     containing found sequences
+
+2004-12-07 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/ShowDicom.cxx, TestWriteWithVTK.cxx : bug fix, now this test pass
+     not at all time
+   * Test/TestCopyRescaleDicom.cxx : rearrange the test to correctly pass...
+     Some fields in BinEntry must be copied to not seg fault when making the :
+              gdcm::File *copy     = new gdcm::File( copyH );
+     and tests are now made on good variables
+
+2004-12-07 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * vtk/vtkGdcmWriter.[h|cxx] : add a first version of vtkGdcmWriter
+   * src/gdcmValEntry.cxx : bug fix when setting the value. Problems of odd
+     length
+   * src/gdcmHeader.cxx : Remove a useless call to Util::DicomString
+   * Add vtkGdcmWriter example and test
+
+2004-12-07 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/TestUtil.cxx : reformat the source code
+   * vtk/vtkGdcmReader.cxx : remove and change prints
+   * src/gdcmValEntry.[cxx|h] : now set the length of the value when calling
+     SetValue
+   * src/gdcmBinEntry.[cxx|h] : SetValue method don't set the length
+   * src/*.cxx : remove all useless call to SetLength of a ValEntry object
+
+2004-12-07 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmPixelWriteConvert.[h|cxx] : ficnished this class
+   * src/gdcmFile.cxx : finished the correctly use of PixelWriteConvert
+
+2004-12-06 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocument.cxx : bug fix when opening the file. All read is followed
+     by an eof to prevent all bad read of the file... and in this case, the
+     file isn't readable. 
+
+2004-12-06 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Example/Volume2Dicom.cxx : comment unused variables
+   * Test/PrintDicomDir.cxx : comment unused variables
+   * Test/BuildUpDicomDir.cxx : remove dbg.Verbose. Remove the FIXME.
+   * src/SQItem.[h|cxx] : remove the PtagHT variable. Remove the AddDocEntry
+     method that is redondant with AddEntry.
+   * src/gdcmDocEntrySet.h : add pure virtual methods common to ElementSet and
+     SQItem
+
+2004-12-04 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Bug fix due my last commit (compilation under Windows).
+   * Example/Volume2Dicom : bug fix in the file and reformatting source code
+   * src/gdcmFile.h : bug fix. Variable type and variable name had same name
+
+2004-12-03 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+   * Huge cleanup:
+     - Remove printf / sprintf
+     - include iostream AFTER gdcm so we don't get warnings
+     - GDCM_NO_ANSI_STRING_STREAM shouldn't be used explitely ouside of gdcm 
+       source
+     - Also remove tons of include from header files, hopefully this should 
+       speeup the compilation time, since it was becoming a dog slow.
+     - Remove gdcm.h as it include way too many files and slow down compilation 
+       (plus it is not up to date)
+     - remove 'using namespace std' this is BAD !
+
+2004-12-03 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Remove memory leaks on the DicomDir
+   * Remove some useless data in DicomDirObject
+   * Add usefull methods in SQItem, to be complient withe the ElementSet
+
+2004-12-03 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFile.[h|cxx] : now use FileType instead of TWriteType.
+
+2004-12-03 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmPixelWriteConvert.[h|cxx] : new class to write data (and in the
+     future, with convertion)
+   * src/gdcmFile.[h|cxx] : the PixelWriteConverter instance replace Pixel_Data
+     and ImageDataSize values. Remove the method to get the PixelReadConverter
+     from the output of the class
+
+2004-12-03 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Rename src/gdcmPixelConvert.[h|cxx] to src/gdcmPixelReadConvert.[h|cxx]
+
+2004-12-02 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * vtk/vtkGdcmReader.cxx : correct error in vtkDebugMacro, vtkWarningMacro
+     and vtkErrorMacro use.
+   * gdcmPython/gdcm.i : corrections to avoid warnings at compilation
+
+2004-12-02 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/TestCopyDicom.cxx : the new dicom created is created empty, without
+     file name in input
+   * src/gdcmSeqEntry.cxx : bug fix in destruction of an element
+   * src/gdcmHeader.cxx : bug fix. Keep the string, otherwise it is destroyed.
+     The string leaves only in the fonction. So when we make a .c_str(), we
+     get the pointeur on the first element, element that will be destroyed 
+     immediately after thee instruction.
+   * src/gdcmDocument.cxx : remove memory leaks. Bug fix when testing if the
+     file has been opened : the test must be made on the content of the 
+     pointer and not directly on the pointer !
+     Code formatting
+
+2004-12-02 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * gdcmPython/gdcm.i : change gdcmHeaderHelper to gdcmSerieHeader. Now,
+     the python part recompiles
+
+2004-11-30 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/ShowDicom.cxx : Change the test to only open one vtkImageViewer.
+     Otherwise, under linux (Graphic card : NVidia / SE : FedoraCore 1) the
+     X session is killed (for my computer... it seems to not be identic on
+     all linux)
+
+2004-11-30 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Test/ShowDicom.cxx : now can be used with an off-screen rendering to
+     avoid problems (otherwise, the difference test between the visible image
+     and the reference is incorrect. If the reference is greater than the
+     screen resolution, it's produce errors).
+     Can be used for only one image. Can be used with a visible flag.
+   * vtk/vtkGdcmReader.cxx : remove commented codes.
+   * vtk/vtkGdcmReader.h : add the gdcmCommon.h include file to avoid warnings
+     under windows at compilation
+   * vtk/vtkgdcmViewer.cxx : reformat the file. Apply a default window/level
+     for grayscale images
+   * vtk/GdcmToBaseline.cxx : new program to easy create the reference image
+
+2004-11-30 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFile.[h|cxx] : bug fix for ACR-LIBIDO files when writting the file
+   * Test/TestAllReadCompareDicom.cxx, TestReadWriteReadCompare.cxx : add
+     tests on the image size X, Y, Z
+
+2004-11-26 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Remove some useless methods in gdcm::Document, gdcm::Header and gdcm::File
+   * Rename gdcmHeaderHelper.[h|cxx] to gdcmSerieHeader.[h|cxx] to be coherent
+     between the class name and the file name
+
+2004-11-25 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/ : fix compilation warnings for the Write method (2 different
+     proto). So Rename 'Write(ifstream* fp' into 'WriteContent(ifstream* fp'
+     fix compilation warnings for the gdcm::Document::TransferSyntaxStrings
+     variable... create a static method in gdcm::Document to access to
+     this variable content.
+
+2004-11-25 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocument.[h|cxx] : set the Transfert Syntax values to the header
+     file, to be accessed by other files (like gdcmFile). Remove commented
+     code. Move the change of the header to the gdcmFile, using the
+     DocEntryArchive
+   * src/gdcmHeader.[h|cxx] : the write is completely made in the Header.
+     To be sure of that (and simplify calls), the Write of the header now
+     gets a file name and not a file pointer (std::ifstream).
+   * src/gdcmFile.[h|cxx] : apply the write file type to the header, using the
+     DocEntryArchive. Remove all open of the written file
+
+2004-11-25 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * vtk/vtkGdcmReader.cxx : compilation bug fix for the vtk part
+
+2004-11-25 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocument.cxx : fix bug... test if the fp is opened to use it
+   * src/gdcmPixelConvert.cxx : calculate the image size when while the grab of
+     the header.
+   * src/gdcmFile.[h|cxx] : remove PixelRead and ImageDataSizeRaw variables and
+     some corresponding methods. Write correctly the file and check before
+     write
+   * Test/TestCopyDicom.cxx, TestReadWriteReadCompare.cxx,
+     TestAllReadCompareDicom.cxx : pass the write of images to RGB and test
+     is now on RGB data (as before my last commit
+   * Example/PrintHeader.cxx, PrintFile.cxx : repad files.
+
+2004-11-24 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmBinEntry.cxx, gdcmSeqEntry.cxx, gdcmSQItem.cxx, gdcmValEntry.cxx :
+     Add a print information of the type of the entry
+   * src/gdcmDocument.cxx : add the write of the preambule of a Dicom file.
+     It was in the gdcmFile, and all write have been regrouped
+   * src/gdcmFile.[h|cxx] : add methods to get the Raw data elements and size.
+     Write correctly all dicom files (in decompressed mode only at this time)
+   * Test/ : test on files are now made using Raw data and not color data if
+     any.
+   * Example/PrintFile.cxx : add more printings
+
+2004-11-24 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * Amelioration of code, remove some code copy. For the loading of
+     BinEntry (in gdcmDocument), add the test to verify if the file is already
+     opened or not.
+
+2004-11-24 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocEntryArchive.[h|cxx] : bug fix and add a method to temporary
+     remove a DocEntry in the header (push an empty DocEntry)
+   * src/gdcmFile.[h|cxx] : remove some useless variables, methods and code
+     lines. Bug fix in the initialization of the PixelConvert and the 
+     DocEntryArchive
+   * src/gdcmElementSet.[h|cxx] : add methods Initialize and GetNext to
+     use in TestCopyDicom (now this test can run under windows... but fails)
+   * Test/TestCopyDicom.cxx : amelioration of the test :
+     - test the pixels written
+     - add test points to quickly find where is the error
+     - can set a file name input and output in arguments
+   * Test/TestAllReadCompareDicom.cxx, TestReadWriteReadCompare.cxx : 
+     amelioration of the test output
+
+2004-11-23 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocEntryArchive.cxx : complete the print function, that prints
+     all replaced DocEntry's
+   * src/gdcmFile.[h|cxx] : remove all changes of the header when getting data.
+     Now, each needed DocEntry to modify is duplicated, modified and inserted
+     to the header using DocEntryArchive. Thus, after save, we can restore the
+     header initial state.
+
+2004-11-22 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmFile.h : fix compilation errors on zorglub linuc computer
+
+2004-11-19 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocEntry.cxx : remove the copy of the DictEntry... there isn't
+     correct to copy it. The DictEntry is specified at the DocEntry creation,
+     then, it musn't change in the time.
+   * src/gdcmDocEntryArchive.[h|cxx] : new class. It's goal is to change the
+     header correctly. At this time, the change is only made for the first
+     level of the Document. In the future, it might consider sequences.
+     The change is made by replacing a DocEntry by an other that is created
+     outside the class. The old value is kept. When we restore the header
+     status, the added DocEntry is deleted and replaced by the old value.
+   * src/gdcmElementSet.h : Set the DocEntryArchive like friend.
+   * src/gdcmFile.[h|cxx] : Use the gdcmDocEntryArchive. Add methods to
+     set the write type to explicit VR, implicit VR or ACR. Add methods to set
+     the write mode to native, decompressed or RGB (but not used at this time)
+
+2004-11-15 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmSeqEntry.cxx : add initialisation of variable SeqTerm
+   * src/gdcmDocument.cxx : add delete of DocEntry's to remove some memory leaks
+
+2004-11-15 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmDocument.cxx : now, when using the ReplaceOrCreateByNumber to
+     set a BinEntry, the binArea is copied (like to set a ValEntry, the string
+     is copied).
+   * Test/TestCopyDicom.cxx, Example/TestCopyDicom.cxx : the image data isn't 
+     set because already copied when copying the BinEntry's of the header
+   * Test/TestAllReadCompareDicom.cxx : remove warnings
+
+2004-11-15 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * FIX : now, the DocEntries are all deleted in the gdcmElementSet.
+     Two problems appear when doing it :
+      - with the gdcmFile : when the GetImageData method is called, the pixels
+        are stored in the gdcmPixelConvert, but a gdcmBinEntry link to these
+        data (pixels). And each structure destruct the data when it's
+        destructed. So we have two destructions for the same data. To solve it,
+        a flag is added in the gdcmBinEntry to indicate if the BinEntry owns the
+        data or not. If it doesn't own data, then they will not destroyed by
+        the gdcmBinEntry.
+      - with the gdcmDicomDir : the sequences (gdcmSQItem) contain DocEntry
+        elements. The DicomDir* (DicomDirPatient, etc.) inherit from SQItem.
+        Thus destruct the DicomDir* elements and the TagHT of the ElementSet 
+        create a double destruction of the same DocEntry's. So, to solve it, 
+        the TagHT is simply cleared and the DicomDir* elements are destroyed.
+   * TODO : add an entry concerning memory leaks in the DicomDir
+
+2004-11-15 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * FIX : src/gdcmDocument.cxx Remove obvious code in the destructor
+   * FIX : src/gdcmPixelConvert : Set to NULL the deleted structures in the
+     squeeze method
+
+2004-11-15 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * FIX: src/gdcmUtil.cxx : to compile with MSVC6
+   * src/gdcmDocument.cxx : fix memory leaks. Fix possible bugs : use an object
+     after it have been deleted
+
+2004-11-16 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+   * FIX: src/* fix the doxygen warnings.
+   * src/gdcmVR.cxx: removed some redundant tests (e.g. LO)
+   * src/gdcmDocument.cxx: FIX ::ComputeRLEInfo() rleSegmentOffsetTable[]
+     was erroneously defined with a size of 15 instead of 16. [many thanks
+     to Jean Michel Rouet for pointing out this bug].
+
+2004-11-15 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+    1. Finish merging JMR patch for writting DICOM from scratch
+    2. Fix -hopefully- bug with MONOCHROME and space vs null character
+    3. Use const ref when possible
+    4. Add a new function InitializeDefaultHeader, which create a template DICOM header (CT image for now)
+    5. A few more comments
+    6. CreateUniqueUID can now be called without parameter"
+
+2004-11-15 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * ENH: Slightly bigger patch:
+    1. Getting toward full integration of JMR patch for writting dicom from scratch
+    2. Update Test to test part of this patch: CreateUniqueUID
+    3. File was not close properly in gdcmDict
+    4. Use of typedef is to be prefered when possible (gdcmDict.cxx)
+    5. Use of const ref instead of copy (speed issue)
+    6. Remove temporary (duplicate) string in TranslateToKey
+    7. Mark extremely dangerous code as such (gdcmDocument.cxx and AddEntry fallback case)
+    8. Do not repeat virtual in subclasses
+    9. Implemented in gdcm::Util two new function: GetIPAddress, and CreateUniqueUID
+
+2004-11-15 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Apply first patch toward better string comparison when dealing with broken 
+    DICOM files. Essentially the string could be padded with a space instead 
+    of a null character as defined by standard
+  
+2004-11-15 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+  * src/gdcmDocument.[cxx|h] : fix memory leaks. The return is suppressed
+    because never used... and in the same time, that's remove some memory leaks
+
+2004-11-15 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+  * src/gdcmFile.cxx : now delete the PixelConvert instance.
+  * In examples and tests : change the type of image data variables from void*
+    to uint8_t*. Remmove all delete on image data variables
+
+2004-11-10 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+  * src/gdcmDocument.cxx : Set the file pointer TP to 0 in the constructors.
+    Verify the file pointer value before open the file, and if it's not null,
+    a verbose message is generated.
+    Close correctly the file when the file isn't considered dicom-like. The
+    correctly close is a call to CloseFile.
+    When closing the file pointer, test if its not null to close the file.
+  * src/gdcmPixelConvert.cxx : bug fix for the SIEMENS_GBS_III-16-ACR_NEMA_1.acr
+    file. For an uncompressed image, the copied data correspond in the least 
+    case to the image size (calculated) or the image size specified in the 
+    header. A verbose is generated if these two size mismatch
+
+2004-11-09 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+  * Test/TestAllReadCompareDicom.cxx : test the existence of the directory
+    using an 'ifstream' other than a 'FILE *'. The previous solution ('FILE *')
+    break under windows (with msvc6 compilation).
+
+2004-11-09 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+  * src/gdcmDicomDir.h : bug fix for the last Boix's commit (problem when
+    compiling with MSVC6)
+
+2004-11-09 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+  * Bugs fix for the Windows build with VC6
+  * CMakeLists.txt : bug fix - The include of the VTK lib is made only when it's
+    needed (only for projects required VTK). If the VTK is included in all
+    projects, there is conflicts with the jpeg lib of vtk when compiling the
+    gdcmjpeg[8,12,16] projects. The first conflict is on the jmorecfg.h file.
+  * src/gdcmUtil.h : export binary_write methods. Otherwise, there's problems
+    when compiling the gdcm_wrap.cxx file (created by the compilation of the
+    gdcm.i file)
+  * vtk/vtkGdcmDemo.cxx : remove the use of std namespace for the cerr use
+    (like it's already made for the cout use). Otherwise, conflict with the
+    std::cerr of vtk.
+
+2004-11-09 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * src/gdcmDicomDit.h the Method typedef is now local to DicomDir class.
+  * gdcmPython/gdcm.i:
+    - comments on the DicomDir::Method related usage added.
+    - now that we use the namespace gdcm, a lot of internal classes do
+      NOT need to be wrapped anymore.
+  * gdcmPython/demo/DicomDirProgressMethod.py (that uses the above
+    DicomDir::Method) new example added.
+
+2004-11-05 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Improve string manipulation. I now inforce the notion of 'DicomString'
+    A DicomString can contain as many \0 as they want
+    and it is *always* of even length.
+    We only support odd length for very rare case. 
+    And in the near future this should be removed.
+
+2004-11-03 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * /binary_write/ gdcm source. Now even on big endian we are writting
+    little endian. This should -heopfully- fix some tests
+
+2004-11-03 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Now the dictionary is compiled into gdcm lib. This is a default
+    behavior, thus any dic file specified is picked before failback to 
+    the one comiled into lib
+
+2004-10-27 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Change internals for gdcmDict. Don't use any 'new' any more.
+    This should definitely solve any leak problem, and we should be
+    as fast as before, as long as don't modify too much the dictionary.
+
+2004-10-25 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * STYLE: ivars should start with a capital letter. 
+  * Accessors should be const to avoid people starting modifying stuff (since this is a ref). 
+  * remove 'virtual' as Style specify subclasses shouldn't reuse the keyword
+  
+2004-10-22 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * Doc/Dicom2004_Part5.pdf added (thanks to JPR).
+  * Dicts/dicomTS2004.dic, dicomV3VM2004.dic, groupNameAbbreviations2004.dic
+    new 2004 dictionaries added (thanks to JPR).
+  * FIX dashboard warning RLEFrame::NumberFragments is now of type unsigned int
+  * CLEANUP_ROUND (15) for gdcmPixelConvert
+    - RLEFrame::NumberFragments is now of type unsigned int
+    - gdcmFile::GetImageData(), GetImageDataIntoVector(), GetImageDataRaw()
+      are now all based on PixelConverter. ::GetImageDataIntoVectorRaw()
+      no longer exists.
+
+2004-10-21 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Initial work in gathering all transfer syntax accessors. clearly 
+   IsDecompressed/IsJPEG2000/IsJPEGLossless/IsRLELossless shouldn't be all 
+   ivars, but only one transfersyntax (class) ivar with equivalent method on 
+   the class.
+  
+2004-10-21 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Removed all FILE* ref and replace by ifstream/ofstream. For now I use a temp 
+    solution with the two files jdatadst.cxx and jdatasrc.cxx, this need to be 
+    discussed (plus I didn't like having a 2000 lines patch not commited)
+
+2004-10-21 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * src/gdcmDocument.cxx: wrong type on return fixed (thanks dashboard)
+  * CLEANUP_ROUND (14) for gdcmPixelConvert
+    - PixelConvert::GetLutRGBA(FILE*) is now GetLutRGBA() (no fp needed)
+    - PixelConvert::BuildRGBImage()(FILE*) is now BuildRGBImage() (no fp needed)
+    - File::GetImageDataIntoVector() doesn't need unnecessary OpenFile() and
+      CloseFile() anymore.
+    - File::GetImageDataRaw() doesn't call GetImageDataIntoVectorRaw()
+      anymore and hence avoids storing a copy of PixelConvert::Decompressed
+      into File::Pixel_Data.
+
+2004-10-20 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * src/gdcmDocument.cxx ftell() return properly stored in a long (i.e.
+    no longer depends on's programmers PMS = Preposterous Mood Swings ;).
+  * CLEANUP_ROUND (13) for gdcmPixelConvert
+    Substituted File::ParsePixelData() with PixelConvert::Print() new
+    method:
+    - src/gdcmParsePixels.cxx removed (only contained File::ParsePixelData())
+    - src/gdcmRLEFrame.cxx, gdcmJPEGFragment.cxx added. Added a ::Print()
+      method to those classes.
+    - src/gdcmFile.[cxx|h]:
+      -- Added a ::Print() method.
+      -- PixelConverter is now a reference instead of a member.
+      -- gdcmPython/gdcm.i: added "using namespace gdcm" in order for
+         gdcm_wrap.cxx to "understand" File::GetPixelConverter()
+
+2004-10-18 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * Doc/CMakeLists.txt, doxygen.config.in: when dot is present the
+    collaboration diagram and inheritance diagram should be generated with
+    doxygen.
+  * Doc/Website/Sidebar.html: Dashboard is now also in the sidebar.
+  * gdcmPython/gdcm.i: gdcmRLEFramesInfo.h gdcmJPEGFragmentsInfo.h are
+    pointlessly wrapped (see
+    http://www.creatis.insa-lyon.fr/pipermail/dcmlib/2004-October/000692.html )
+  * CLEANUP_ROUND (12) for gdcmPixelConvert (sugar is my friend stage)
+    - Header::GetLUTRGBA() moved to PixelConvert::GetLutRGBA()
+    - vtk/vtkGdcmReader.cxx: adapted to displacment of Header::GetLUTRGBA()
+    - Document::RLEInfo and JPEGInfo are now pointer members (Swig thing)
+    - src/gdcmFile.[cxx|h] and gdcmPixelConvert.[cxx|h]:
+      -- File::Initialise: PixelConverter setup moved away to
+           PixelConverter::GrabInformationsFromHeader()
+      -- File::GetImageDataIntoVector(): Lut R + Lut G + Lut B color table
+         interpretation moved away to PixelConverter::BuildRGBImage()
+
+2004-10-16 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Remove GDCM_EXPORT keyword from gdcm::DirList due to :
+    http://support.microsoft.com/support/kb/articles/Q168/9/58.ASP
+
+2004-10-15 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * src/gdcmDebug.cxx last ditch attempt to get warning/error messages
+    displayed on Win32 when a brutal abort() occurs (because of uncatched
+    exception). See TODO new entry of this commit for more on this.
+  * TODO added new entry.
+  * CLEANUP_ROUND (12) for gdcmPixelConvert (nicotine is my friend stage)
+    src/gdcmFile.[cxx|h] and gdcmPixelConvert.[cxx|h]:
+    - HandleColor is no longer called from gdcmFile.cxx
+    - gdcmPixelConvert.cxx clean up on method arguments and internal
+      variable names for semantical coherence.
+
+2004-10-14 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Finished lossless transition, not only do we now read all lossless jpeg
+  images, without the need of the Cornwell lib, but we do read them properly now
+  * To reduce code (well to avoid code duplication), I defined a common place
+  for jpeg read/write: gdcmJpeg.cxx. Now gdcmJpeg[8,12 16] include this file and
+  redefine symbols. This is not perfect but this the best solution I found for a
+  compilation time jpeg option.
+
+2004-10-13 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Update jpeg ijg lib to support lossless jpeg implementation
+    For more info look in jpeg/libijg/README.GDCM.txt for necessary steps to
+    reproduce at home.
+  * Also added a special copyright for dcmtk since we use their bugfixes.
+  Thanks dcmtk crew !
+
+2004-10-13 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * Doc/Website/MailingList.html added (Sidebar.html changed accordingly).
+  * gdcmPython/gdcm.i: fix for compilation of wrappers (Note: %include order
+    matters, as stated in warning note at beginning of %include section).
+  * src/gdcmDicomDir*.[cxx|h]: coding style
+  * src/gdcmDocument.h: doxygen \ref seems uncompatible with \todo.
+  * src/gdcmJpeg8.cxx: doxygen fix.
+  * CLEANUP_ROUND (12) for gdcmPixelConvert (seing the ligth stage)
+    src/gdcmFile.[cxx|h] and gdcmPixelConvert.[cxx|h]: color handling moved
+    from File:: to PixelConvert::.
+
+2004-10-12 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * CLEANUP_ROUND (11) for gdcmPixelConvert (cafeine is my friend stage)
+    src/gdcmFile.[cxx|h] and gdcmPixelConvert.[cxx|h]:
+     - more code moved away from File:: to PixelConvert::
+     - fat setup of PixelConverter set in place in File::Initialise.
+
+2004-10-12 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Apply patch for namespace in gdcm. Didn't rename files for keeping a sort of
+  namespace at the file system level. So now you should convert your examples
+  like this:
+    gdcmHeader  ->   gdcm::Header
+  It would be nice if people keep in mind to no open the namespace, since it
+  allows compilation on broken plateform which were defining common symbol in
+  the standard namespace (like LP, Unknown ...)
+
+2004-10-10 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * CLEANUP_ROUND (10) for gdcmPixelConvert (Xanax is my friend stage)
+    The JPEG fragments are now parsed at the same stage than the RLE
+    information. All code related to JPEG is now in gdcmPixelConvert:
+    - src/gdcmJPEGFragment.h and gdcmJPEGFragmentsInfo.[h|cxx] added 
+    - src/gdcmJpeg12.cxx, gdcmJpeg2000.cxx and gdcmJpeg8.cxx no longer
+      export a gdcmFile:: method. Those are simply global functions
+      (for the time being this is better than having them attach to
+       either gdcmFile:: or gdcmPixelConvert::).
+    - src/gdcmDocument.[cxx|h], gdcmDocument:: now parser the JPEG fragments
+      and stores the result in a gdcmJPEGFragmentsInfo.
+    - src/gdcmFile.[cxx|h] and gdcmPixelConvert.[cxx|h]: all JPEG related
+      code (among other stuff) moved away from gdcmFile:; to 
+      gdcmPixelConvert::
+
+2004-10-08 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * src/gdcmCommon.h now declares int8_t for non stdint.h plateforms.
+  * CLEANUP_ROUND (7) for gdcmPixelConvert (lost at sea)
+    - src/gdcmFile.h gdcmPixelConvert.cxx gdcmPixelConvert.h gdcmRLE.cxx:
+      clean up of RLE related code. 
+  * CLEANUP_ROUND (8) for gdcmPixelConvert (end of RLE nigthmare)
+    - src/gdcmRLE.cxx removed
+    - src/gdcmPixelConvert.cxx all RLE code is now in PixelConvert::
+    - src/CMakeLists.txt gdcmFile.[cxx|h] changed accordingly
+    - src/gdcmRLEFrame*.h gdcmPixelConvert is now a friend class.
+  * CLEANUP_ROUND (9) for gdcmPixelConvert
+    - src/gdcmFile.[cxx|h} gdcmPixelConvert.[cxx|h], SwapZone(),
+      ConvertReorderEndianity(), ConvertDecmpres12BitsTo16Bits() moved
+      away from gdcmFile:: to gdcmPixelConvert::.
+
+2004-10-07 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * CLEANUP_ROUND (5) for gdcmPixelConvert (Upshit creek without a paddle)
+    - src/gdcmDocument.[cxx|h] Parse7Fe0 renamed to ComputeRLEInfo.
+      This is because Parse7Fe0 used to parse the pixels to compute the
+      length. This task was passed over to FindDocEntryLengthOB() a long
+      time ago, EXCEPT I forgot the OW case...
+      Hence Parse7Fe0 was no longer necessary. When renaming to ComputeRLEInfo
+      we just recylce the code for parsing RLE fragments and computing
+      offsets.
+  * CLEANUP_ROUND (6) for gdcmPixelConvert (man, I need a paddle bad)
+    - src/gdcmRLE.cxx: is now much simpler and avoids code replication
+        with the retired Parse7Fe0().
+    - src/gdcmRLEFrame.h: type fix for properly computing OffSet[]
+    - src/gdcmDocument.cxx: segments offset are now correct + clean up.
+
+2004-10-06 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * CLEANUP_ROUND (3) for gdcmPixelConvert (nightmare stage)
+    - src/gdcmRLEFramesInfo.[cxx|h], gdcmRLEFrame.h added
+    - src/gdcmDocument.[cxx|h] ::Parse7FE0 now sets up the RLEInfo.
+    - src/CMakeLists.txt: alphabetic order reodering + new entries.
+  * CLEANUP_ROUND (4) for gdcmPixelConvert
+    - src/gdcmDocument.[cxx|h] ::ParseDES and ::ParseSQ no longer bother
+      to return an unused length.
+
+2004-10-09 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Remove all sprintf from the code to centralize in one spot in gdcmUtil
+    this should be cleanner from the plane view. The iostream are erally a pain
+    to use to do simple stuff.
+
+2004-10-04 Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+  * Redo the compilation of the ijg jpeg library. Now only one source is
+    necesseray. No need to rename file by hand what so ever. CMake handle the
+    copying of the file within different directory, configure header file to
+    modify some symbol. The only addition made to ijg wasd a mangle table so
+    that symbol are different whether we are within 8bits or 12bits.
+
+2004-10-01 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * Added documentation of vtkgdcmReader on Website:
+     - testvtkGdcmReader.cxx renamed to vtkGdcmDemo.cxx (to be compatible
+       with it's binary name).
+     - vtk/vtkGdcmDemo.cxx and vtkgdcmViewer.cxx: added comments for
+       the Website to be more complete.
+     - Doc/doxygen.config.in: vtk/vtkGdcmReader.cxx now appears on 
+       doxygenated documentation.
+     - Doc/DoxyVtkGdcmReaderExamples.txt added
+       (see http://www.creatis.insa-lyon.fr/Public/Gdcm/html.developper/
+                  DoxyVtkGdmReaderExamples.html )
+  * src/win32, vtk/win32 manually maintained .dsp and .dsw removed.
+  * CLEANUP_ROUND (3) for gdcmPixelConvert
+   - src/gdcmFile.cxx, gdcmFile.h splitting GetImageDataIntoVectorRaw
+
+2004-09-29 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * CLEANUP_ROUND (2) for gdcmPixelConvert
+   - src/gdcmFile.cxx, gdcmFile.h splitting GetImageDataIntoVectorRaw
+
+2004-09-29 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * CLEANUP_ROUND for gdcmPixelConvert:
+    - src/gdcmFile.cxx, gdcmFile.h, gdcmHeader.cxx, gdcmHeader.h clean up
+    - src/gdcmPixelStuff[h|cxx] removed
+    - src/gdcmPixelConvert[h|cxx] added. Preparatory work included.
+    - src/CMakeLists.txt changed accordingly
+  * GDCMHOME clean up:
+    - MANIFEST.in, WrapSwig.py, WrapVTK.py, distutilsWrapping.py and
+      gdcmVersion.py moved to newly created ATTIC related
+      gdcmPython/SetupOldies/ directory.
+  * Autotools clean up:
+    - */*/Makefile.am removed AT EXCEPTION of gdcmPython/Makefile.am
+    - autogen.sh configure.in acinclude.m4 python.m4 removed 
+
+2004-09-27 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * src/*.cxx *.h Reference to License.htm fixed to License.html.
+  * Doc/CMakeLists.txt, doxygen.config.in: fix.
+  * Doc/Website/ConformanceSummary.html, minimal conformance statement added.
+
+2004-09-24 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * TODO updated with Mathieu suggestions. I proposed a template for
+    describing TODO entries and used it for new entries.
+  * Added Doc/Website/CodingStyle.html, Developpers.html,
+    DeveloppersPython.html, GdcmDataCvs.html and
+    DownloadVersion0_1.html, DownloadVersion0_3.html.
+  * Some Doc/*.txt Doxygen files (which do not really concern the
+    documentation itself, but the website) moved to html and
+    placed in directory Doc/Website:
+    - Doc/DoxyDevelInstal.txt moved to Doc/Website/Developpers.html
+    - Doc/DoxyInstallation.txt moved to Doc/Website/Installation.html
+    - Doc/DoxyIntroduction.txt included in Doc/Website/Main.html
+  * Doc/DoxyfileDeveloppers, DoxyfileUsers, Makefile.am oldies removed.
+  * CMakeLists.txt changed accordingly.
+  * DEVELOPPER spread out in Doc/Website/Developpers.html, CodingStyle.html,
+    DeveloppersPython.html
+  * INSTALL nows refers to Doc/Website/Installation.html
+
+2004-09-23 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * Added Doc/Website directory, that contains a first raw version
+    of gdcm Web site.
+
+2004-09-23 Jean-Pierre Roux
+  * FIX In order not to be poluted any longer by casting problems,
+    the member VoidArea of gdcmBinEntry is now uint8_t* (instead of void *)
+    we can now delete[] it safely 
+  * VoidArea is now called BinArea (less confusing name),
+    and all the methods called ...VoidArea... are now ... BinArea...
+  * class gdcmObject is now called gdcmDicomDirObject (less confusing name)
+
+2004-09-22 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * src/gdcmDocument.cxx: gdcmDocument::~gdcmDocument() doesn't clear (nor
+    clear) TagHT, which is an inherited member of gdcmElementSet. It is
+    up to the destructor of gdcmElementSet to clean up TagHt and it's
+    pointed content.
+
+2004-09-21 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * Test/CMakeLists.txt: update to follow gdcmData renamings.
+  * src/gdcmCommon.h, gdcmDocument.cxx: doxygen typos
+
+2004-09-17 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * ENH: added some utility method that builds a flat dictionary
+    holding all the Dicom entries contained in the recursive structure
+    of a gdcmElementSet. Refer to add FlatHashTablePrint.cxx for 
+    an example of usage.
+    - src/gdcmDocument.[h|cxx] added BuildFlatHashTableRecurse() and
+      BuildFlatHashTable() that build a flat dictionary.
+    - src/gdcmElementSet.h: added a new private GetTag() accessor.
+      gdcmDocument is now a friend of gdcmElementSet.
+    - src/gdcmElementSet.cxx: clean up.
+    - Example/FlatHashTablePrint.cxx added.
+    - Example/CmakeLists.txt changed accordingly
+
+2004-09-16 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * gdcmDocEntrySet::SQDepthLevel and gdcmDocEntrySet::BaseTagKey attributes
+    moved away from gdcmDocEntrySet (since this class is an abstract class
+    acting like an interface). SQDepthLevel and BaseTagKey are now
+    in class 
+    - src/gdcmDocEntrySet.[h|cxx] removal of SQDepthLevel and BaseTagKey
+      and associated accessors. Doxygenation of the class.
+    - src/gdcmSQItem.[h|cxx] SQDepthLevel and BaseTagKey and associated
+      accessors added.
+    - src/gdcmSeqEntry.[h|cxx]: constructor doesn't handle depth anymore.
+      Use SQDepthLevel accessor instead. ::Print() adapted.
+    - src/gdcmElementSet.cxx changed according to changes in gdcmSeqEntry.
+    - src/gdcmDocument.cxx changed accordingly.
+
+2004-09-13 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * Preparation of writing a gdcmHeader iterator: generalisation of gdcmTagKey
+    - The following is the doxygen comment of the typedef declaration
+      of gdcmTagKey in src/gdcmCommon.h:
+           gdcmTagKey is made to old an "universal" (as in URL, Universal
+           Ressource Locator)  key to a gdcmDocEntry i.e. a dicom tag.
+           A dicom tag always has a group and an element, but a set of tags
+           embeded in various (optionally nested) sequences and sharing
+           the same group and element all share the same (group, element)
+           "identifier". Hence the (group, element) cannot be used as an
+           identifier (in gdcm we shall refer to a "TagKey") of a tag.
+           In order to construct a proper tag identifier (i.e. a key) we
+           consider the following definition of a TagKey:
+           - let Group, Element be the string representation of the
+             group and element dicom tag members,
+           - let ItemNumber be the string representation of the integer
+             index of the considered item number of a sequence,
+           Let the key of a tag embeded in a sequence, noted SeqTag, be
+           the form:
+              /ItemNumber#Group|Element
+           where "/", "#" and "|" are characters acting as separators.
+           Then the general form of a gdcmTagKey is given by:
+              Group|Element<SeqTag>
+           where <SeqTag> means NO or many instances of SeqTag.
+           Hence the gdcmTagKey of a tag not "leaving" in a sequence is the
+           string e.g.
+               0028|1201
+           but the gdcmTagKey of a tag "embeded" is the first item of
+           a sequence, itself nested in the third item of a sequence is the
+           string e.g.
+               0004|1220/2#0008|0082/0#0008|0090
+    - src/gdcmDocEntry.h: added a new Key (of type gdcmTagKey) member, in
+      order to hold the new sequence compatible key. Previously, the 
+      GetKey() method would look in the underlying gdcmDictEntry.
+    - src/gdcmDocEntry.cxx:
+      -- constructor now copies the underlying DictEntry key, in the local
+         Key member.
+      -- ::Print: displays the member Key, instead of the (group, element).
+    - src/gdcmCommon.h: added some comments on typedef gdcmTagKey.
+    - src/gdcmDocEntrySet.h:xi
+      -- ::ParseDES() now setups the gdcmTagKey of the sequence it is parsing.
+      -- now has a new BaseTagKey member.
+      -- STYLE.
+  * src/gdcmValEntry.[h|cxx], src/gdcmBinEntry.[h|cxx]: the member VoidArea,
+    previously a member of gdcmValEntry, moved to gdcmBinEntry were is
+    truly belongs.
+    This poses the problem with the semantics of the following lines
+       LoadEntryVoidArea(0x0028,0x1201);  // R    LUT
+       LoadEntryVoidArea(0x0028,0x1202);  // G    LUT
+       LoadEntryVoidArea(0x0028,0x1203);  // B    LUT
+    in gdcmDocument::gdcmDocument(std::string const & ). Please refer
+    to the long FIXME note for what the problem is. Nevertheless in
+    order to get things working the dicom dictionary was altered !
+    Please fix things urgently...
+  * Dicts/dicomV3.dic WRONGLY altered (this means we introduced a uncorrect
+    information), see above note on moving the member VoidArea. Nevertheless
+    the following entries previously correctly set as US are now inproperly
+    set to OW:
+      0028 1201 OW IMG Red Palette Color Lookup Table Data
+      0028 1202 OW IMG Green Palette Color Lookup Table Data
+      0028 1203 OW IMG Blue Palette Color Lookup Table Data
+  * src/gdcmDocEntry.[h|cxx], src/gdcmSeqEntry.h: SQDepthLevel member
+    of gdcmDocEntry moved to gdcmSeqEntry.
+  * src/gdcmSeqEntry.cxx: STYLE.
+
+2004-08-04 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * Test/TestAllEntryVerify.cxx minor fix and added comments.
+
+2004-08-03 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * gdcmPython/testSuite.py: all the test suite in python is now moved
+    to it's C++ version (see gdcmData/TestAllEntryVerifyReference.txt)
+  * Test/CMakeLists.txt adapted to renaming of files in gdcmData
+  * gdcm/TODO and src/gdcmDictSet.h cleaned up frow the "TODO Swig" oldies
+
+2004-08-02 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * gdcmPython/CMakeLists.txt: SWIG_FLAGS doesn't declare includeall
+    to avoid inclusion recursion until STL is reached.
+  * src/gdcmDocument.[h|cxx]: exceptions substituted to errno C-style
+    mecanism. errno.h is not included in gdcm anymore.
+  * src/gdcmException.h: introduced new gdcmFormatUnexpected class
+    (gdcmFormatError now inherits from gdcmFormatUnexpected).
+  * TODO updated
+  * gdcmPython/testSuite.py checks on CR-MONO1-10-chest.dcm moved to
+    gdcmData/TestAllEntryVerifyReference.txt
+  * Test/TestAllEntryVerify.cxx is now effective (used always return true)
+  * src/gdcmDocument.[cxx|h]: constructors no longer use the bool
+    exception_on_error parameter.
+    - src/gdcmFile.[cxx|h], src/gdcmHeader.[cxx|h] changed accordingly,
+    - vtk/vtkGdcmReader.cxx changed accordingly,
+    - Example/*.cxx and Test/*.cxx changed accordingly.
+
+2004-07-06 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * src/gdcmDicomDir.cxx, gdcmDocEntrySet.cxx: removed inclusion of errno.h
+  * src/gdcmDocument.[h|cxx], gdcmFile.[h|cxx], gdcmHeader.[h|cxx]:
+    enable_sequences removed from gdcmHeader constructor and dependencies.
+  * Example/PrintHeader.cxx: fixed accordingly (enable_sequences removal).
+  * gdcmPython/demo/PrintHeader.py: dummy fix.
+  * src/gdcmDocument.[h|cxx], gdcmFile.[h|cxx], gdcmHeader.[h|cxx]:
+    skip_shadow removed from gdcmHeader constructor and dependencies.
+  * Example/*.cxx and Test/*.cxx changed accordingly.
+
+2004-07-27 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+  * Test/CMakeLists.txt: newly re-introduced SIEMENS_Sonata-12-MONO2-SQ.dcm
+    in gdcmData (previously known as E00001S03I0015.dcm) is blacklisted.
+
+2004-07-21 Jean-Pierre Roux
+  * FIX Now, Parsing and Printing a DICOMDIR do work!
+       ( troubles remain in makeDicomDir and BuildUpDicomDir :-(
+ 
+2004-07-20 Jean-Pierre Roux
+  * FIX Some brain damaged headers have Zero-Lenght fields 
+        for 'Transfert Syntax UID', or 'Media Stored SOP Class UID'.
+
+2004-07-19 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+   * src/gdcmCommon.h, gdcmDict.cxx, gdcmTS.cxx : bug fix for msvc6 compilation
+   * src/gdcmDebug.[h|cxx] : bug fix for msvc6 compilation. Replace the dbg
+     variable (instance of gdcmDebug) by a definition macro, and the instance
+     is now in static in the gdcmDebug class
+   * src/gdcmSQItem.h : (FIXME) remove an undefined method
+   * Test/PrintAllDocument.cxx : bug fix in the result of the test
+
+2004-07-06 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+   * WARNING: ctest now depends more tightly on gdcmData. You should
+     check out gdcmData properly for things to run smoothly...
+   * src/gdcmDocument.cxx MAX_SIZE_LOAD_ELEMENT_VALUE is set back to 0xfff
+     (4096) for "ctest -R TestAllEntryVerify" to be able to run (i.e.
+     we need the pixels not be loaded in order to use the ValEntry
+     that displays position and size).
+   * Test/TestAllEntryVerify.cxx a new low level test now seems fair.
+     This is a C++ based equivalent of gdcmPython/testSuite.py that should
+     be deprecated. If you have any doubts about the advantages of a
+     modern scripting language (read Python) versus grass root C++ (i.e.
+     without lex + yacc, because of gdcm commitement to MS-VC++, sighhh),
+     I suggest you compare TestAllEntryVerify.cxx (639 lines, without the
+     reference file gdcmData/TestAllEntryVerifyReference.txt) and testSuite.py.
+        Anyhow, consider documenting the gdcmData images in 
+     gdcmData/TestAllEntryVerifyReference.txt (and please run ctest before
+     commiting changes).
+   * Test/CMakeLists.txt:
+      - now uses TestAllEntryVerify.cxx
+      - specific comments on oldACR00001.ima (now renamed in gdcmData
+        to SIEMENS_GBS_III-16-ACR_NEMA_1.acr) moved away to
+        gdcmData/TestAllEntryVerifyReference.txt
+   * TODO updated.
+
+2004-07-02 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+   * src/*.[h|cxx] : typedef clean up
+     - guint16 and guint32 removed. Use ISO C uint16_t, uint32_t instead.
+     - TagKey renamed to gdcmTagKey (for external usage)
+     - VRKey renamed to gdcmVRKey (for external usage)
+     - removal of typedef duplication.
+     - Removed all unecessary inline keyword from class inline definitions.
+     - Some method|function(void) declarations replaced with method|function().
+   * src/jpeg/libijg12/jdhuff12.c:
+      - printf polluting ctest removed.
+      - TAB removal for comminting
+   * Test:
+     - TestAllReadCompareDicom.cxx: added a test that compares all the
+       images in gdcmDataImages.h with corresponding images in 
+       gdcmData/BaselineDicom/. When baseline images are not present
+       this test creates them.
+       Note: we need to validate each reference image, but before that
+             I'd like to rename them with a more explicit name...
+     - CMakeLists.txt: changed accordingly.
+   * Example/*.cxx: examples now only include gdcm.h (as opposed to 
+     including each header needed).
+
+2004-07-01 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+   * Test/*.cxx and Example/*.cxx: moved some examples away from the
+     test suite to the Example directory. Are concerned:
+     - PrintHeader.cxx
+     - TestDcm2Acr.cxx
+     - TestFindTags.cxx
+     - TestWrite.cxx was
+     - TestWriteSimple.cxx
+   * Test/CMakeLists.txt: added some comments on reasons for black listing
+     image gdcmData/oldACR00001.ima
+
+2004-06-30 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+   * Test/CmakeList.txt: removed the following from black list (to be coherent
+     with removal from gdcmData):
+      - gdcm-MR-PHILIPS-16-Multi-Seq.fixed.dcm
+      - gdcm-MR-PHILIPS-16.dcm
+      - US.3405.1.dcm
+     Added the following because after last cvs update, they cause
+       ctest -R TestReadWriteReadCompare 
+     to segfault:
+      - gdcm-MR-SIEMENS-16-1.acr
+      - oldACR00001.ima
+   * Test/TestReadWriteReadCompare.cxx was properly written (with a call
+     to gdcmFile::SetImageData()) BUT since gdcmFile is brain damaged (see
+     new comments in this file) we temporarily (sigh) move to a weaker
+     form of test...
+   * Test/CmakeList.txt: with the change to Test/TestReadWriteReadCompare.cxx
+     we don't need to black list the following images anymore:
+      - 8BitsUncompressedColor.dcm
+      - OT-PAL-8-face.dcm
+      - US-PAL-8-10x-echo.dcm
+   * src/gdcmDocument.[h|cxx]: RE-Reverting to version 1.42 with the proper
+     fixes and the beautified code ;-)
+     This fixes the bug introduced in version 1.42 (when beautifying)
+     that made the parsing of 8BitsRunLengthColor.dcm unproper.
+     Note: ctest was blind to this bug (this means we need to still
+           improve the test suite). The bug could be detected by using
+           gdcmbin/bin/PrintDocument $GDCM_DATA/8BitsRunLengthColor.dcm
+           or by using
+           gdcmbin/bin/ReadWrite $GDCM_DATA/8BitsRunLengthColor.dcm
+           and by displaying the (garbage) produced file temp.XDCM...
+
+2004-06-29 Jean-Pierre Roux
+   FIX : - remove Frog's beautified, but never checked 'Parse7FE0' code,
+         - replace by uggly but working old code :-(
+   A lot of things should be OK again.
+   It's really urgent to have a test suite that *tests*, 
+   to prevent Frog's beautifying sessions to break all the stuff
+   (twice, withing a fortnigh ...)    
+
+2004-06-28 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+   * Test/TestWriteRead.cxx and TestReadWrite.cxx merged (because of
+     redundancy) to added Test/TestReadWriteReadCompare.cxx
+   * Test/CmakeList.txt: because the compare test of
+     Test/TestReadWriteReadCompare.cxx fails, the following images are
+     black listed: - 8BitsUncompressedColor.dcm
+                   - OT-PAL-8-face.dcm
+                   - US-PAL-8-10x-echo.dcm
+   * src/gdcmDocument.cxx: for broken (non DICOM V3 conformal) images
+     (e.g. gdcm-JPEG-LossLess3a.dcm see comments in
+     gdcm/gdcmPython/testSuite.py for details) ::FindDocLengthOB() had
+     and ad-hoc kludge. This kludge is now removed, and on encountering
+     such an image (OB field brain damaged) we set errno. Then in 
+     ::FindDocLength() we "fix" the length as being ALL what remains
+     in the file (until EOF). We then proceed, hoping for the best...
+     This fixes a SegFault in ShowDicom when trying to write such an
+     image.
+   * Test/CmakeList.txt: 8BitsRunLengthColor.dcm is now blacklisted
+     (because TestWriteRead breaks on it, after a non conformal commit?).
+     ctest now runs properly, except for MakeDicomDir (which was always
+     broken) and the Python related stuff (still not fixed).
+   
+2004-06-24 Jean-Pierre Roux
+  ADD : Examples/WriteRead, that acts like the former Test/TestWriteRead
+  FIX : Test/TestReadWrite now iterates on all the file names 
+                          (instead of infinite loop)
+  ENH : Test/TestWriteRead now iterates on all the file names 
+
+2004-06-28 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+   * Test/TestReadWrite.cxx: now uses all the images of gdcmData.
+
+2004-06-24 Jean-Pierre Roux
+   FIX : - now Write drops LUT Descriptors and LUTs (if any)
+           when SamplesPerPixel =3
+         - now Write is no longer confused by 
+          'BitsAllocated = 12" and 'BitsStored=12"
+         - "UN" value representation Elements are now written correctly 
+               (their legth is stored on 4 bytes -just like OB, OW, and SQ-)
+   ENH : - now gdcmHeader has its own Write methods 
+           (in order to split the job that has not to be done 
+           for gdcmDicomDir)
+
+2004-06-23 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+   * Test/PrintAllDocument.cxx: looping on files is now effective. It used to
+     loop on the same image until memory went out. 
+     Note: this means we still have gobs of memory loss in PrintDocument
+   * src/gdcmDocument.cxx: fixes problem on parsing on file
+     gdcmData/16BitsJpegLosslessGrayScale.dcm.
+
+2004-06-24 Jean-Pierre Roux
+   FIX : Write - All the Sequences and Sequence Item are now written 
+            as 'no length' stuff, and a Sequence Delimitor aor an Item Delimitor
+            is added a the end, when necessary.
+            - A lot of brain-damaged images, that were read correctly are 
+              now written correctly
+            - length compatible BinEntry are now loaded correctly 
+              (even for odd groups) 
+        Note : only Explicit Value Representation was checked.
+               (question : is implicit VR really necessary for gdcm ?)
+
+2004-06-23 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+   * DEVELOPPER: added a proposition of coding style.
+   * src/gdcmDocEntry.h: removed every inline declaration (for test of 
+     coding style).
+
+2004-06-23 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+   * gdcmDocEntry::PrintCommonPart() and ::WriteCommonPart() removed.
+     Use the gdcmDocEntry::Print() and Write() instead.
+   * src/gdcmDocument.cxx: bug fix.
+
+2004-06-22 Jean-Pierre Roux
+   FIX : gdcmDocument.cxx
+      - Now we do recognize the JpegLossLess format (there was a misstyping in
+        code 'beautyfication' :-(
+      - Now we automaticaticaly load the Luts, if any
+
+2004-06-22 Jean-Pierre Roux
+   In order : to write Sequences, whatever their imbrication level, 
+            : to allow user to create his own Sequences
+   a lot of modif where necessary (adding, moving, or virtualising methods)
+
+   WARNING : save your own sources *before* cvs up !
+
+   - gdcmBinEntry
+     ADD virtual void Write(FILE *fp, FileType filetype);
+  
+   - gdcmDocEntry
+     ADD virtual void Write(FILE *fp, FileType filetype);
+     ADD void gdcmDocEntry::WriteCommonPart(FILE *fp, FileType filetype);
+  
+   - gdcmDocEntrySet
+     ADD virtual void Write (FILE *fp, FileType filetype)=0;
+     ADD virtual gdcmDocEntry *GetDocEntryByNumber(guint16 group,guint16 element) = 0;
+     ADD gdcmDocEntry *GetDocEntryByName(std::string name);
+     ADD virtual std::string GetEntryByNumber(guint16 group,guint16 element) = 0;
+     ADD std::string GetEntryByName(TagName name);            
+     ADD gdcmDictEntry *NewVirtualDictEntry(guint16 group, 
+                                            guint16 element,
+                                            std::string vr     = "unkn",
+                                            std::string fourth = "unkn",
+                                            std::string name   = "unkn"); 
+     ADD gdcmValEntry *NewValEntryByNumber(guint16 group, guint16 element);  
+     ADD gdcmBinEntry *NewBinEntryByNumber(guint16 group, guint16 element); 
+     ADD gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element); 
+     ADD gdcmDocEntry *NewDocEntryByName  (std::string Name);   
+     ADD gdcmDictEntry *GetDictEntryByName   (std::string Name);
+     ADD gdcmDictEntry *GetDictEntryByNumber(guint16, guint16);
+     REM virtual gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element)=0;
+     REM virtual gdcmDocEntry *NewDocEntryByName  (std::string Name)=0;
+  
+   - gdcmDocument
+     ADD virtual bool WriteF(FileType type); // New stuff, with recursive exploration
+     ADD virtual std::string GetEntryByName    (TagName tagName);
+     ADD virtual std::string GetEntryVRByName  (TagName tagName);
+     REM virtual bool Write(FILE *, FileType);
+     REM virtual void WriteEntryTagVRLength(gdcmDocEntry *tag,
+                                        FILE *_fp, FileType type);
+     REM virtual void WriteEntryValue(gdcmDocEntry *tag,FILE *_fp,FileType type);
+     REM virtual bool WriteEntry(gdcmDocEntry *tag,FILE *_fp,FileType type);
+     REM virtual bool WriteEntries(FILE *_fp,FileType type);
+     REM virtual std::string GetEntryByName    (std::string tagName);
+     REM virtual std::string GetEntryVRByName  (std::string tagName);
+     REM gdcmDictEntry *GetDictEntryByName  (std::string Name);
+     REM gdcmDictEntry *GetDictEntryByNumber(guint16, guint16);
+     REM gdcmDictEntry *NewVirtualDictEntry(guint16 group, 
+                                            guint16 element,
+                                            std::string vr     = "unkn",
+                                            std::string fourth = "unkn",
+                                            std::string name   = "unkn");
+     REM gdcmDocEntry *NewDocEntryByNumber(guint16 group, guint16 element);
+     REM gdcmDocEntry *NewDocEntryByName  (std::string Name);
+     REM gdcmValEntry *NewValEntryByNumber(guint16 group, guint16 element); 
+     REM gdcmBinEntry *NewBinEntryByNumber(guint16 group, guint16 element); 
+                                             
+   - gdcmElementSet
+     ADD virtual void Write(FILE *fp, FileType filetype);
+     
+   - gdcmSeqEntry
+     ADD virtual void Write(FILE *fp,FileType filetype);
+ 
+   - gdcmSQItem
+     ADD virtual void Write(FILE *fp, FileType filetype);
+     ADD virtual std::string GetEntryByNumber(guint16 group, guint16 element);         
+     REM std::string GetEntryByNumber(guint16 group, guint16 element);
+     REM std::string GetEntryByName(TagName name);
+
+   - gdcmValEntry
+    ADD virtual void gdcmValEntry::Write(FILE *fp, FileType filetype); 
+              
+2004-06-21 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+    * Test/TestWriteSimple.cxx: fix to gdcmHeader-gdcmHeaderHelper revamping.
+      The default constructor invoked by the line
+         gdcmHeader *f1 = new gdcmHeader( header );
+      was gdcmHeader::gdcmHeader(bool) instead of the expected
+      gdcmHeader::gdcmHeader(std::string const &, bool = false, bool, bool).
+      Hence the parsing wasn't executed... See also below.
+    * src/gdcmHeader.h: the declaration of gdcmHeader::gdcmHeader(bool)
+      as explicit constructor didn't do the trick to fix the above problem.
+      Could anyone explain why ?
+    * src/gdcmBinEntry.cxx, gdcmValEntry.cxx: gdcmBinEntry::Print() now
+      properly calls gdcmValEntry::Print() (that was weed out from 
+      code related to gdcmBinEntry).
+
+2004-06-20 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+    * In order to fix memory leaks:
+     - Test/TestWriteSimple.cxx: added cleaning of free store through
+       some delete calls.
+     - src/gdcmBinEntry.cxx: fix to avoid SegFault.
+     - src/gdcmDicomDir.[cxx|h]: fixed initialisation in constructor
+       gdcmDicomDir::gdcmDicomDir(bool) [either the constructor itself
+       (through the call to ::AddDicomDirMeta()) or the destructor
+       would crash when deleting uninitialized ::metaElems].
+     - src/gdcmDictEntry.cxx: annotation of ununderstood memory leak.
+     - src/gdcmDocument.cxx:
+       -- ::~gdcmDocument() destructor now cleans up all dictionary entries
+          from dynamic stores.
+       -- ::ParseDES() misplaced deletion of temporary NewDocEntry
+          was causing memory leaks.
+     - src/gdcmSQItem.cxx:
+       -- ::~gdcmSQItem() dummy code cleaned (learned that deletion is
+          cleanly handled with polymophism: sorry but my milage is low).
+       -- ::SetEntryByNumber(string, guint16, guint16) now cleanly allocates
+          a gdcmValENtry, and makes no assumption on type (gdcmDocEntry,
+          gdcmSeqEntry vs gdcmValEntry) of existing entry (when present).
+          This avoids SegFaulting.
+     - src/gdcmSQItem.h: coding style.
+    * Conclusion:
+     - Test/TestWriteSimple still severely sucks. The output image content
+       (when $(GDCMDATA_HOME)/012345.002.050.dcm in input) is brain
+       damaged when displayed with vtkgdcmViewer.
+     - on memory leaks: TestWriteSimple leaks really less (see entry
+       of 2004-06-18 in Changelog file for the call to valgrind).
+     - on segfaults: ctest now passes all the tests but one (no more
+       segfaults).
+    * Erroneous leading white fix:
+     - src/gdcmDict.cxx: getline(from,xxx) doesn't remove the leading
+       white[s] (as opposed to from >> xxx, that removes it [them].
+     - src/gdcmTS.cxx: ditto.
+     - gdcmPython/testSuite.py: dirty related kludge removed.
+    * src/*: remaining references to gdcmParser removed.
+    * src/*[cxx|h]: added copy[way]left header.
+
+
+2004-06-18 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+    * In order to fix writing of dicom files:
+     - Test/TestWriteSimple.cxx: a simpler example of writing.
+     - Test/CMakeLists.txt changed accordingly.
+     - src/gdcmDocument.cxx:
+       -- The destructor now recursilvely removes potential sequences.
+       -- Bug fix in ::IsJPEG2000()
+       -- ::ReplaceOrCreateByNumber(std::string, guint16, guint16)
+          now handles promotion of gdcmDocEntry to gdcmValEntry in a cleaner
+          manner.
+       -- ::GetValEntryByNumber(guint16, guint16) now defined (as opposed
+          to only declared) and build on top of
+          ::GetDocEntryByNumber(guint16, guint16).
+       -- ::SetEntryByNumber() now uses GetValEntryByNumber(group, element)
+     - src/gdcmElementSet.[h|cxx]: added ::RemoveEntry(gdcmDocEntry *)
+       for usage in destructor and treatement of promotion in
+       ::ReplaceOrCreateByNumber().
+     - src/gdcmSQItem.cxx: destructor should better handle his job.
+      Test/TestWriteSimple now runs (or at least it DOES something).
+    * We can now start hutting memory links. A good starting point is:
+      valgrind -q --skin=memcheck --leak-check=yes --leak-resolution=high
+      --num-callers=100 --show-reachable=yes gdcmTests TestWriteSimple
+      $(GDCMDATA_HOME)/012345.002.050.dcm foo.dcm
+
+2004-06-18 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+    * Valgrind note: after Mathieu Malaterre teached me how to read
+      the valgrind FAQ ;-] (see http://valgrind.kde.org/faq.html), I
+      learned that:
+          Using gcc, you can force the STL to use malloc and to free memory as
+          soon as possible by globally disabling memory caching.
+          With 3.2.2 and later, you should export the environment variable
+          GLIBCPP_FORCE_NEW before running your program.
+      By setting GLIBCPP_FORCE_NEW, STL related memory leak messages of gdcm
+      simply vanish (it is still not clear to me, whether this means that
+      STL std::string leaks or if valgrind believes it leaks...).
+    * Fixing of SegFault of Test/makeDicomDir (as shown by ctest or by
+      running bin/gdcmTests makeDicomDir):
+      - src/gdcmDicomDir.cxx: dynamic casting used + clean up.
+      - Test/makeDicomDir.cxx now properly traps empty lists and returns
+        with 1.
+      NOW, makeDicomDir cleanly fails (in ctest terminology) instead of
+      SegFaulting (I drowned in DicomDir related code when trying to
+      understand why the list is empty...).
+    * src/gdcmDocument.h: first BSD license header try.
+    * Doc/License.txt added.
+
+2004-06-15 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+    * src/gdcmDocument.[h|cxx]:
+      - Clean up of the Transfer related predicates. They are now all based
+        on new method isGivenTransferSyntax, that (should) handle properly
+        the padding problem.
+      - general clean up, simplification, and coding style.
+      - Specific clean up of Parse7FE0() (umproperly named actually).
+    * gdcmPython/testSuite.py: an odd temporary kludge introduced.
+
+2004-06-14 Jean-Pierre Roux      
+   *  gdcmSeqEntry.cxx
+      - fix the display of Sequence Delimitor (SQDepthLevel pb)
+      - fix the display of SQItem ordinal number
+      - add the GetSQItemByOrdinalNumber method
+      - remove some useless never written private methods   
+      
+2004-06-14 Jean-Pierre Roux
+   * gdcmBinEntry.cxx 
+      - adding a constructor taking a gdcmDocEntry as an input param
+      - ReplaceOrCreateByNumber now returns :
+         a gdcmBinEntry * if a Binary (void *) value is passed as a param
+         a gdcmValEntry * if a string value is passed as a param
+   * dcmDocument.cxx
+      - SetEntryByNumber now allows setting gdcmValEntry or gdcmBinEntry, 
+         according to the param type (no longer sets a gdcmDocEntry)
+      - GetValEntryByNumber, GetBinEntryByNumber added
+      - NewValEntryByNumber and NewBinEntryByNumber added
+   * gdcmFile.cxx
+      - Pixel Data are now linked to the (7fe0,0010) elements, after reading
+   * gdcmSQItem.h
+      - GetSQItemNumber and SetSQItemNumber added, to provide 
+            a (relative) Item identier inside a given Sequence
+            \warning : some pb remaining around this number
+            will be solved asap
+      - AddEntry now takes the Item Number as a param    
+   * gdcmValEntry.cxx 
+      - adding a constructor taking a gdcmDocEntry as an input param   
+
+2004-06-14 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+    * Memory leak hunt with the following command:
+      valgrind --leak-check=yes --leak-resolution=high --num-callers=40
+               --show-reachable=yes gdcmTests PrintDocument
+      It looks like many (all?) leaks are due to the STL (or a bad usage
+      of the STL. The lines producing the leaks now have a comment with
+      a "MEMORY LEAK" tag: you can retrieve them with 
+          grep "MEMORY LEAK" src/*
+      Here are two typical examples which I can't help fixing:
+      -----
+          #include <string>
+          int main() {
+             std::string name;
+             char * test = "babo";
+             name = test;    //// <--- valgrind detects 960 bytes lost in
+                             ////   call to std::string::operator=(char const*)
+             name.clear();   //// Doesn't help !
+             return 0;
+          }
+      -----
+          #include <string>
+          #include <iostream>
+          int main() {
+             std::string line;
+             std::cout << "Type a bunch of characters followed by RETURN: ";
+             getline(std::cin, line);   //// <--- valgrind dectects a loss
+                                        //// of 1320 bytes in call to
+                                        /// std::basic_istream<>& std::getline<>
+            return 0;
+          }
+      -----
+
+
+2004-06-10 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+    * src/gdcmHeader.[cxx|h]:
+      - Predicates on the Transfer syntax (of the form Is[JPEG|RLE]*)
+        and related, moved away to gdcmDocument.
+      - Accessors (on the form [Get|Set]Entry*) set up to expose publicly
+        the corresponding protected accessors of inherited class
+        gdcmDocument, removed ! As a consequence gdcmFile had to be 
+        declared friend of class gdcmDocument (see below).
+      - operator< moved to gdcmDocument (in fact it belongs to gdcmDicomDir).
+      - Clean up of undefined or unused methods.
+    * src/gdcmFile.[cxx|h]: added SetEntryByNumber (in order to take into
+      account the changes to gdcmHeader.h).
+    * src/gdcmDocument.h:
+      - gdcmFile is now a friend class (in order to take into account the
+        changes to gdcmHeader.h).
+      - Predicates on the Transfer syntax (of the form Is[JPEG|RLE]*) added
+        (see changes to gdcmHeader.h).
+      - Accessors (reading on the form GetEntry*) are now public.
+      - Clean up of undefined or unused methods.
+    * src/gdcmDocument.cxx:
+      - adaptation to changes to gdcmDocument.h
+      - ::OpenFile now writes a verbose message when file cannot be opened.
+      - some std::string properly set to VRKey
+    * src/gdcmDicomDir.h: historical references to gdcmHeader changed to
+      references to gdcmDocument. 
+    * Test/TestFindTags.cxx: changed accordingly to above changes.
+    * gdcmPython/testSuite.py: adapted to renaming of acr files in 
+      cvs repository gdcmData.
+
+2004-06-09 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+    * src/gdcmValEntry.h: member voidArea type changed from char* to void*.
+    * src/gdcmBinEntry.h: member voidArea commented out, since it potentially
+      conflicts with gdcmValEntry::voidArea.
+    * src/gdcmValEntry.cxx: unmatching comment wiped out.
+    * src/gdcmVR.[h|cxx]: added two predicates that partition the possible
+      Value representation between StringRepresentable and BinaryRepresentable.
+    * src/gdcmDocument.cxx: 
+      - method ParseDES: proper indentation restored and usage of
+        gdcmVR::IsVROfGdcmStringRepresentable wired in.
+      - method LoadDocEntry: the fingerprint left in the SetValue() of
+        unloaded entries (length > MaxSizeLoadEntry) had curiously been
+        removed. Reverting to previous code segment with the proper
+        dynamic_cast< gdcmValEntry* >.
+        Note: this was (partially) breaking the python test suite
+              (gdcmPython/testSuite.py) that made usage of the above
+              fingerprint to check presence of "Pixel Data".
+    * src/gdcmDocEntry.h: coding style.
+    * gdcmPython/__init__.py: environement variable GDCM_DATA_PATH is
+      now taken into account.
+    * gdcmPython/gdcm.i: adaptation to the new internal representation
+      of gdcm (exit gdcmParser, hello gdcmDocument).
+    * gdcmPython/testSuite.py: quick and dirty fix for loading vtkgdcmPython
+      on posix.
+    * gdcmPython/demo/PrintHeader.py: doesn't use the gdcmDocument::Print()
+      anymore, but instead prints the loaded Python dictionary.
+    * .... alas, the python testSuite is still broken.
+
+2004-05-18 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+    * gdcmPython/gdcm.i : remove useless lines concerning the gdcmGlobal
+      gdcmGlob
+    * gdcmPython/setup.py : replace the use of cvar.gdcmGlob to gdcmGlobal
+    * src/gdcmUtil.h : export methods
+
+2004-05-16  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+    * Some more cleanup/enhancement in gdcmPython/CMakeLists.txt getting close
+      to right behavior
+    * Initial addition of automatic python testing
+    * Initial addition of automatic image comparison
+
+2004-05-04 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+    * src/gdcmCommon.h, gdcmDicomDir.cxx, gdcmFile.cxx, gdcmHeaderHelper.h,
+      gdcmParser.cxx, gdcmParser.h : bug fix for the Microsoft .Net compilation
+
+2004-05-04 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+     * src/gdcmFile.cxx, gdcmHeader.cxx : bug fix for the msvc compilation
+     * Test/ShowDicom.cxx : bug fix for msvc compilation
+     * vtk/vtkgdcmViewer.cxx : bug fix for msvc compilation
+
+2004-05-04 Jean-Pierre Roux
+     * ADD Taking into account the 'Dicom Sequences' leads up to introduce
+       new concepts (and new classes) :
+       a 'gdcmDocument' is composed of a set of Doc Entries, that are
+        - elementary gdcmDocEntries (former gdcmHeaderEntries)
+        - Sequence Doc Entries (gdcmSeqEntries)
+       a Sequence is composed of Items.
+       Each item is a set of Doc Entries (this is recursive)
+       The non uniqueness of the 'Dicom tag' is due to this recursivity
+       (never taken into account)
+       Our unability to add a new 'entry' in the header
+       at the proper location (neither in the H-Table (map or multimap),
+       nor in the Chained List is also due to this recursivity.
+       Don't try, right now, to use/modify/compile these new sources :
+       nothing is finished.
+       We just commit all the stuff, 'as is', in order not to loose it.
+
+2004-05-04 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+     * vtk/vtkGdcmReader.cxx : bug fix in the setting of file name
+     
+2004-05-03 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+     * vtk/vtkGdcmReader.cxx : bug fix when loading a list of files using the
+       file prefix (SetFilePrefix)
+
+2004-05-02  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * Add a new test: ShowDicom, for now this is just the c++ version of
+       checkRead.sh, later it will be able to compare the image read against a
+       baseline.
+     * Replace the DEBUG on the stack with a global entry in cmake interface:
+       GDCM_DEBUG, so you can turn verbosity ON/OFF for debug statement.
+
+2004-04-30  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * Add an example subdir, with a real example on how to read + write a 
+       dicom image
+
+2004-04-30  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+     * Doc/gdcmUML.xmi added raw UML class view (umbrello format)
+     * Doc/CMakeLists.txt: the main page is now properly differentiated
+       between the developper and user version.
+     * Doc/doxygen.config.in: dropped search related obsolete flags
+     * src/gdcmParser.h, gdcmHeader.h: doxygenation
+
+2004-04-29  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+     * DEVELOPPER: added some helpfull comments for compile/test/install
+       when using cmake.
+
+2004-04-29  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * ENH: 1. Remove remp solution of gdcmTests.cxx+ gdcmMain directly in 
+               src directory, now generated in the build dir.
+            2. Tests as mentionned smarter
+            3. Some clean up
+            4. Add a new method in gdcmDict that return the PubDict by name 
+          this is interesting for 3rd party lib like ITK, 
+          where we could set the institution name / patient name...
+
+       * ENH: 1. Now the test suite is working for real
+              2. All binaries are now output in the gdcm-bin directory 
+                 (this was not true before)
+
+2004-04-28  Jean-Pierre Roux
+     * ENH add the provisional  gdcmHeader::SQDepthLevel to allow 
+           SeQuence indented printing of Dicom Header.
+     * ENH merge methods gdcmParser::Parse and gdcmParser::LoadHeaderEntries
+           into the single gdcmParser::LoadHeaderEntries for efficiency purpose.
+      Computation of SQDepthLevel is now part of gdcmHeader constructor
+     * ENH add self defined param 'new' to PrintHeader to 'show' the SeQuence
+           tree-like structure of a Dicom Header.
+     * FIX Test code cleaning     
+           
+2004-04-25  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * ENH: Adding automatic testing
+       1. Need a DartConfig.cmake to submit to public
+       2. Add a test driver gdcmTest.cxx
+       3. gdcmTestMain, an helper for the main test driver gdcmTest
+       4. Files in Test don't have a main anymore, this becomes interesting 
+          when we add more and more tests, thus dsw don't have to load 
+          too many projects
+     * ENH: Adding a GDCM_DATA_ROOT for testing
+     * ENH: Remove redundancie about GDCM_DICT stuff, now we only need to modify
+       one file instead of seven + some small cleanup
+
+2004-04-22  Jean-Pierre Roux
+     * ENH Minor changes to the Print() methods.
+     * ADD gdcmParser::PrintEntryNiceSQ() to allow SQ-indented
+           Header printing. Example given with :
+      > PrintHeader fileName  2 new
+          (SQ based tree-like structure still to be done for the Header ...)
+      
+2004-04-22  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * ENH: Some cosmetic clean up for compilation with -W -Wall -Werror
+         1. I have added some unsigned where needed
+         2. Some function parameter not used -> (void)
+         3. In gdcmDicomDir.cxx, add GDCM_DICOMDIR_NONE case
+         4. g++ don't like character '\' in comment
+         5. #define jpeg_create_decompress  jCreaDecompress
+                    this really need to be fixed
+         6. virtualize destructor of gdcmObject ... leakage
+         7. sscanf(g->first.c_str(),"%x",&gr_bid); 
+                    this also really need to be fixed
+         8. gdcm/src/jpeg/libijg8/CMakeLists.txt, 
+                    remove compression file 
+                    (as we only do decompression, right ?)     
+     * ENH: Change malloc/calloc/free with c++ equivalent
+
+2004-04-21  Jean-Pierre Roux
+     * FIX gdcmHeaderHelper::GetXSpacing
+           when a single value is found (bug ?), xpacing is now 
+           defaulted to yspacing
+      
+2004-04-19  Jean-Pierre Roux
+     * ADD gdcmData/Wrist.pap (PAPYRUS 3.0 -single frame-) for checking purpose
+     * ENH add parameters :
+               bool  exception_on_error = false, 
+               bool  enable_sequences   = false,
+          bool  ignore_shadow      = false
+           to the gdcmFile constructors to be full gdcmParser compliant
+     * FIX vtk/vtkGdcmReader.cxx now uses  enable_sequences = true in gdcmFile
+           to allow reading of PAPYRUS 3.0 files 
+         
+2004-04-06  Jean-Pierre Roux
+     * ADD gdcmData/E00001S03I0015.dcm for SQ checking purpose
+     
+2004-04-02  Jean-Pierre Roux
+     * ADD : Test/checksequence.sh, for a general recap on SQ pb
+     * FIX : gdcmParser::WriteEntryTagVRLength emprovement of special treatement
+             for Philips spurious Tag fffe|0000 while rewritting Dicom files
+        
+2004-03-30  Jean-Pierre Roux
+     * FIX gdcmParser::ReplaceOrCreateByNumber shouldn't seg fault any more 
+         for ACR file, written out as DICOM files (hope so...)
+
+2004-03-30  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+     * src/gdcmParser.[cxx|h] and gdcmHeader.[cxx.h]: gdcmHeader::Write split
+       in WriteEntryTagVRLength and WriteEntryValue. Those methods were
+       moved to base class gdcmParser and only the specialisation is kept
+       in gdcmHeader.
+     * src/gdcmParser.[cxx|h]: ReplaceOrCreateByNumber(char*, guint16, guint16)
+       trashed out (because ReplaceOrCreateByNumber(string, guint16, guint16)
+       already does the job.
+     * src/gdcmDicomDir.[cxx|h]: WriteDicomDirEntries renamed to WriteEntries
+       (to be consistent with gdcmParser::WriteEntries).
+
+2004-03-30 Benoit Regrain
+     * vtk/vtkGdcmReader.[h|cxx] : fix the read of 3 gdcmHeader when making an
+       upate of the object's instance. It's passed to 2 in the unfavorable
+       case : one in the ExecuteInformation, one in the ExecuteData
+
+2004-03-29  Jean-Pierre Roux
+     * ENH : Check on file type to be written moved
+             from gdcmParser::WriteEntry to gdcmParser::WriteEntries
+     * FIX : gdcmObject::ResetBoundaries now stops properly
+             when end-of-list is reached
+      : gdcmVersion modified (as Benoit Regrain asked)
+
+2004-03-29  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+     * src/gdcmParser.cxx: removal of all TAB character. Indentation fixed.
+     * src/gdcmUtil.cxx: added forgotten iostream include.
+     * src/gdcmCommon.h: FileType enum entry DICOMDIR removed (since
+       equivalent to ExplicitVR in existing code).
+
+2004-03-27  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+     * src/gdcmUtil.[cxx|h] split in two. Additional file gdcmGlobal.[cxx|h]
+       now contains all the gdcmGlobal related code.
+     * minor coding style and doxygenation changes.
+
+2004-03-26  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+     * src/gdcmUtil.[cxx|h] split in two. Additional file gdcmDebug.[cxx|h]
+       now contains all the Debug related code.
+     * minor clean-up of includes in src/*.cxx
+     * src/gdcmUtil.[cxx|h] _cleanString C style function (replaced with
+       CreateCleanString) removed.
+     * src/gdcmUtil.[cxx|h] _CreateCleanString renamed to CreateCleanString
+     * Doc/DoxyMainPageUser.txt added.
+     * Doc/Doc/DoxyfileUsers updated to version 1.3.4 of Doxygen.
+     * src/gdcmCommon.h now defines getcwd for Win32 (moved away from
+       src/gdcmDirList.cxx)
+
+2004-03-24  Jean-Pierre Roux
+     * FIX a lot of little surface modifications to be doxygen 1.3.6 compliant
+
+2004-03-23  Jean-Pierre Roux
+     * FIX Now gdcmFile::SwapZone doesn't seg faults any longer for
+           big endian made volumes
+     * ENH Now gdcmParser constructor and destructor are protected to forbid
+           end user to instanciate class gdcmParser
+          (only gdcmHeader and gdcmDicomDir are meaningfull)
+
+2004-03-22 Benoit Regrain
+     * FIX : src/gdcmDicomDir.cxx : make windows compilable
+     * FIX : gdcmPython/gdcm.i : change gdcmStudy to gdcmDicomDirStudy and
+             gdcmSerie to gdcmDicomDirSerie
+
+2004-03-19  Jean-Pierre Roux
+     * ENH Now the tree-like structure describing a DICOMDIR comming from
+           an already existing DICOMDIR file is consistent with
+           the home-made tree-like structure build ex-nihilo
+           or build from the files held (recursively) in a Directory
+           functions gdcmDicomDir::CheckBoundaries()
+           gdcmObject::SetBoundaries() added
+
+2004-03-17  Jean-Pierre Roux
+     * REM (Eric Boix bug) : removal of meaningless
+                             gdcmDicomDirImage::NewImage function.
+     * FIX now file names and directory name are written properly in the
+           DICOMDIR
+     * FIX now gdcmDicomDir constructor may be call without any trick
+           about the name
+
+2004-03-16  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+     * FIX (JPR bug) : src/gdcmDicomDirImage.cxx added missing definition
+                       of gdcmDicomDirImage::NewImage as empty function.
+
+2004-02-28  Jean-Pierre Roux
+     * ENH add gdcmDicomDir:NewPatient
+           add gdcmDicomDirPatient:NewStudy
+           add gdcmDicomDirStudy:NewSerie
+           add gdcmDicomDirSerie:NewImage
+      to allow making gdcDicomDir object.
+     * ADD PrintDicomDir executable that uses gdcmDicomDir tree-like structure
+          (as opposite to the gdcmHeader chained list)
+
+2004-02-11 Benoit Regrain
+     * FIX : memory leaks and the set of ArgDelete methods in gdcmDicomDir
+             when using from python
+             
+2004-02-10 Benoit Regrain
+     * FIX : bug fix in the gdcmDirList for the recursivity in directories
+     * FIX : in gdcmDicomDir when the directory is empty
+     * ENH : add callback and methods to get the progression of dicomDir
+             directory parsing
+
+2004-02-06 Jean-Pierre Roux
+     * ENH : - now gdcmDicomDir::CreateDicomDir() returns also the meta elements
+             - GDCM_META added to gdcmDicomDirType
+             - class gdcmMeta created
+     * ENH : - A brief summary is now displayed at the beginning of
+             'testDicomDir' to help disaster magnitude estimation
+     * REM : Now useless Test/explDICOMDIR.cxx
+
+2004-02-05 Benoit Regrain
+     * ENH : add methods in gdcmObject to get the hash table or the list of
+             header entries
+     * FIX : wrapping python for ListPatient, ListStudy, ListSerie, ListImage
+     * FIX : wrapping python for TagHeaderEntryHT
+
+2004-02-04 Benoit Regrain
+     * FIX : even length for some strings when writting the dicom dir
+     * FIX : sort the images in the dicom dir
+     * FIX : Bug fix for python use of dicom dir
+     * ADD : a python demo
+
+2004-02-04 Jean-Pierre Roux
+     * FIX : Final solution (?) for icone embedded images
+     * FIX : dicomVR.dic Overlay group is not *only* 6000, but 60xxx
+             (see http://medical.nema.org/dicom/2003/03_06PU.PDF)
+             add groups 6002, 6004, 6006, to allow 'clean' parsing of
+             gdcmData/gdcm-MR-SIEMENS-16.acr1
+     * ENH add gdcmData/checkWriteExplicit.sh gdcmData/checkWriteImplicit.sh
+           to make full checking easier
+        
+2004-02-04 Benoit Regrain
+     * FIX : WriteEntries : coding style & logic in parameters
+     * FIX : Set the elements to create the DicomDir in a dictionary file
+
+2004-02-03 Benoit Regrain
+     * gdcmDirList : to parse a hard drive directory in recursive (or not)
+     * gdcmDicomDir : add the load of directory
+     * Bug fix and print add-on
+
+2004-02-03 Jean-Pierre Roux
+     * ENH gdcmParser : allows "DICM" files, with NO group '0002'
+     * FIX handling 'non string elements' unsecure area (LUT, overlays, etc)
+     * FIX Dicts/dicomV3.dic : Add a few missing 'group length' Elements 
+     * FIX gdcmParser.cxx : 'group length' elements are now considered 
+           as integers, even for shadow groups, when file is Implicit VR
+        
+2004-02-02 Jean-Pierre Roux
+     * FIX : gdcmWrite : equal_range() for multimap doesn't return a 'second' 
+             iterator on last
+             of the last synonym :-(
+     * FIX : gdcmWrite::WriteBase : method stops if Pixels not yet Read (except 
+             for DICOMDIR ;-)
+     * ENH gdcmData/checkWrite.sh :modif for full check of Explicit VR writting
+     * FIX taking into account the possible 7fe0,0010 multiplicity        
+     * FIX add GRPixel,NumPixel,countGrPixel (gdcmParser protected members)
+           to allow removal of references to 7fe0,0010, to deal with
+      ACR-NEMA images, when 0028,0200 is meaningfull
+
+2004-01-31 Jean-Pierre Roux
+     * FIX gdcmParser::WriteEntries : when a VR is tagged as 'Unknown'
+           no longer writes 'Un' on disk
+     * FIX SQ elements with actual length are now dealt with corectly
+     * FIX gdcmFile::WriteBase make the difference, for color images, between
+           the length (for Palette expanded images)
+           and Raw Length (non expanded image + Palette)
+     * FIX Dicts/dicomV3.dic : removal of 'CTX' (context dependant) VR
+           (that broke Write). Replaced by UL.
+           Aware user will reload the field if he 
+           thinks it's necesssary
+             
+2004-01-30 Jean-Pierre Roux
+     * gdcmParser::CheckSwap() now defaults the filetype to ACR 
+       when 'dirty Acr' is found, to be compliant with the new 
+       IsReadable() methods.
+       
+     * gdcmHeaderHelper :add Pixel Type 'FD', for dealing with 'double' images.
+      (no DOUBLE images in kosher DICOM, 
+      but so usefull for people that miss them ;-)
+      
+     * add Test/testDicomDir.cxx, Test/makeDicomDir.cxx , Test/explDICOMDIR.cxx
+       DICOMDIR related utilities (not checked as Windoze compliant)
+
+2004-01-28 Jean-Pierre Roux
+     * upgrade GdcmHeaderEntry Print Method for DICOMDIR
+
+2004-01-27 Jean-Pierre Roux
+     * gdcmParser constructor has a new boolean param,'ignore_shadow', 
+             to allow skipping the shadow elements, to save memory space.
+        The TRUE value for this param has to be used 
+        with a FALSE value for the 'enable_sequence' param.
+        ('public elements' may be embedded in 'shadow Sequences')
+     * gdcmHeader methods now deal with 'embedded icones images' in the header
+             (even when an 'icone image sequence' is announced by the 
+        element (0x0088,0x0200), but there is NO icone at all ...
+        
+     * gdcmHeader sometimes Image Location value doesn't follow  
+             the supposed processor endianity (see gdcmData/cr172241.dcm).
+             Fixed
+
+     * gdcmHeader add the method
+             IterHT  GetHeaderEntrySameNumber(grPixel,numPixel);
+        to get *all* the Header Entries with the same tag.
+        GetHeaderEntrySameName is probabely *useless* 
+        (no meaning : Name is *not* an identifier within the Dictionary)
+
+2004-01-26 Benoit Regrain
+     * Bug fix in the print of hexadecimal representations. Remove long fields 
+       in the print and add a third level of print to print them
+
+2004-01-23 Benoit Regrain
+     * Bug fix on field having a VR = 'UI'. Assume that is a string field
+     * Bug fix on test suite after remove the strip made on not string fields
+     * Split the IsReadable method between gdcmParser which test that the file
+       is dicom and gdcmHeader which test that it's an image file
+
+2004-01-22 Benoit Regrain
+     * DicomDir : clean code, add methods, set variables in protected or private
+     * gdcmUtil : bug fix for the clean string method
+
+2004-01-19 Benoit Regrain
+     * Add the use of shadow dictionaries
+     * bug fix and coding style
+
+2004-01-19 Benoit Regrain
+     * src/gdcmFile.cxx : bug fix concerning the close of file
+     * src/gdcmParser.[h|cxx] : remove obvious Pub informations
+     * Add the update of header entries using the shadow library
+
+2004-01-19 Benoit Regrain
+     * removal of file gdcmHeader2.cxx
+     * split class gdcmHeader into gdcmParser and gdcmHeader, with gdcmHeader
+       inheriting from gdcmParser. This split is to prepare the integration
+       of dicom dir parsing
+     * bug fix under python
+
+2004-01-16 Jean-Pierre Roux
+    * REM removal of class gdcmHeaderEntrySet
+    * REM removal of files gdcmHeaderEntrySet.cxx, gdcmHeaderEntrySet.h
+    * ADD add file gdcmHeader2.cxx 
+    * ADD add method gdcmHeader::SetPrintLevel (for PrintHeader)
+
+2004-01-15 Benoit Regrain
+     * src/gdcmDicSet.[h|cxx] : add virtual entries to have a reference of
+       entries created while parsing the header. Thus, they will be destroyed
+       when the gdcmDictSet will be destroyed
+     * src/gdcmHeader.cxx, gdcmHeaderEntrySet.cxx : uses virtual entries of
+       gdcmDictSet
+
+2004-01-15 Benoit Regrain
+     * vtk/vtkGdcmReader.cxx : bug fix : before, with python only, the program
+       made a fatal error because of the memory release at the end of program.
+       The problem was in vtkGdcmReader::ExecuteData where we were allocate
+       some memory and vtk seems to have some problems with that.
+     * src/gdcmHeaderEntrySet.cxx : bug fix for std lib and cout
+
+2004-01-14 Benoit Regrain
+     * src/gdcmHeaderEntry.[h|cxx] : gdcmElValue -> gdcmHeaderEntry
+     * src/gdcmHeaderEntrySet.[h|cxx] : gdcmElValSet -> gdcmHeaderEntrySet
+     * src/*.[h|cxx] : make changes due to class name changes
+     * gdcmPython/demo/*.py : bug fix due to method names
+
+2004-01-13 Benoit Regrain
+     * src/*.[h|cxx] : coding style
+     * vtk/*.[h|cxx] : coding style
+
+2004-01-13 Benoit Regrain
+     * gdcmPython/testSuite.py : test the readable flag of file for tests
+     * src/gdcmDict.cxx, gdcmElValSet.cxx : bug fix under windows for prints.
+       It's lied to the stl compilation by MSVC (windows, always windows...)
+     * src/gdcmIdo.h, gdcmHeaderIdo.cxx : remove the Ido unused files
+
+2004-01-12 Benoit Regrain
+     * src/*.h : add comments
+     * src/gdcmDictSet.h : set the method BuildDictPath in public
+     * src/gdcmTS.cxx, gdcmVR.cxx : use now a dictionary file other than to be
+       directly setted in the source code
+     * Dicts/dicomTS.dic, dicomVR.dic : 2 new dictionary files loaded by
+       gdcmTS and gdcmVR
+
+2004-01-09 Benoit Regrain
+     * gdcmPython/gdcmVersion.py : add a gdcmVERSION variable information
+     * setup.py : use a reference to gdcmVERSION
+
+2004-01-07 Benoit Regrain
+     * Modification to compile with the distutils.
+     * Bug fix in code
+
+2003-12-10 Benoit Regrain
+     * gdcmHeader is now aggregating gdcmFile, and not derived into. Thus, we
+       can use a gdcmHeaderHelper to load data
+     * gdcmPython/testSuite.py : make the testSuite compliant with modifications
+       made in the source code
+
+2003-12-10 Benoit Regrain
+     * Update Windows projects and .cvsignore files
+
+2003-11-12 Jean-Pierre Roux
+     * ENH gdcmHeader constructor has one more parameter (default value : false)
+           that allows the user to 'go inside' the SeQuences only
+           if he wants to.
+           gdcmElValSet:Print takes it into account
+
+2003-11-12  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * ENH: Update gdcmPython/CMakeLists
+     * FIX: (gdcmHeaderHelper) GetRescale and GetSlope
+     * FIX: (gdcmElValSet) char 'tag' was overiding private members (VC++)
+
+2003-11-10 Jean-Pierre Roux
+      * FIX : gdcmHeader::LoadElements is now based
+             on the ListTag listElem member,
+             not longer on the TagElValueHT tagHt member
+      * ENH : PrintPubElVal shows (temporarily) both results,
+             with the tagHt member and the listElem member.
+        (it's easier to 'see' the problems when using Printheader)
+
+      * FIX : old private member LgrElem is now splitted into
+             ReadLength   : Length actually found on disk (updated only
+                       if bug fixing is necessary), for internal
+             use only
+        UsableLength : Updated by FixFoundLength, to fix a bug
+                       or to allow Parser going on.
+        Will allow to re-write a kosher header when a SeQuence
+        with a length (not 0000) is found
+      Warning : gdcmFile::Write still uses the TagHt (not ListElem)
+           because gdcmElValSet::Add does not update ListElem
+      (to be written)
+
+2003-11-07 Jean-Pierre Roux
+     * FIX misstyping in Transfert Syntax name table
+     * ENH gdcmHeader::FixFoundLength now allow to 'go inside' tge SeQuences
+          when they have an actual length (not 0000 nor FFFFF)
+     (Nobody should care of it, but DICOMDIR explorers)
+
+2003-11-06  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * ENH: vtkgdcmViewer now works with LUT dicom (OT-PAL-face ...)
+
+2003-11-05  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * ENH: vtkGdcmReader now supports LUT !
+          (vtkgdcmViewer for now is not able to use them though)
+
+2003-11-05 Jean-Pierre Roux
+     * in testSuite.py : new files names for checking the package
+     * FIX : Forgot to commit gdcmFile::GetImageDataSizeRaw();
+             that returns the pixel area size to the *aware* (vtk) user
+             that DOESN'T want to turn the PALETTE COLOR image into an RGB image
+
+2003-11-05 Benoit Regrain
+     * in testSuite.py : Modify the rules for checking the paths
+                       : Explicit error messages
+     * in __init__.py  : Related modif
+
+2003-11-03 Jean-Pierre Roux
+     * add gdcmHeaderHelper::GetNumberOfScalarComponentsRaw()
+           to be used by aware (vtk) users that want to manage
+           LUT (and no to turn the PALETTE image into an RGB pixels one)
+     * GetPixelType now returns 8U for 24 Bits images
+                    (vtkGdcmReader compliant)           
+      
+2003-10-31 Jean-Pierre Roux
+     * Removal of *all* gdcmData images and add them again
+       in order to loose the 'history' of un-anonymised images
+       
+2003-10-31 Jean-Pierre Roux
+     * RMV : removal of useless jBitsInJsample.h 
+           for both 8 and 12 Bits JPEG Lossy Libraries
+
+2003-10-31 Jean-Pierre Roux
+     * ENH : Add the functions gdcmFile::GetImageDataRaw 
+                               gdcmFile::GetImageDataIntoVectorRaw
+             that act as GetImageData and GetImageDataIntoVector
+             except the making of an RGB Plane from Gray Plane + LUT
+             Intended to aware (vtk) users who know how to manage
+             such an image :
+             After gdcmHeader :
+              GetLUTRGBA return a R,G,B,A LUT if any
+              lgrTotaleRaw gives the 'Raw' length
+              GetImageDataRaw returns the gray Plane
+     * FIX : no more dirty trick for 'Segmented xxx Palette Color Lookup' images
+             (They stay Grey, just like with other Dicom viewers :-(
+
+2003-10-30 Jean-Pierre Roux
+     * FIX : a VC++ intended syntax modif broke the 12/12 Bytes expanding
+             
+2003-10-29  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * ENH: Can be used like this '$vtkgdcmViewer *.dcm' with *.dcm 
+      being coherents dicom files.
+     
+2003-10-29  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * FIX: DOH ! Forgot about windo$e users, they couldn't read lossless jpeg,
+           from medcon lib !
+     * ENH: Turn it into DOS file type to match libgdcmijpeg8.dsp file type 
+     * ENH: Two steps is necessary to please VC++ compiler...
+     * FIX: DOH ! libgdcmijpg8 -> libgdcmljpeg
+     * ENH: Add include dir to medcon lib
+     * FIX: only one function is being exported for now ! 
+           You should use GLOBAL(return type) see ljpg/jpeg.h for more info
+            
+2003-10-29 Jean-Pierre Roux
+      * adding  gdcmHeader::GetLUTRGBA
+        returns a 4 * 256 Bytes Reg/Green/Blue/Alpha vtk compliant LUT
+          --> Mathieu, the modif u're waiting for is not yet committed
+      * removal of now useless GetLUTRed,GetLUTGreen,GetLUTBlue,GetLUTRGB
+
+2003-10-27 Jean-Pierre Roux
+      * adding some xmedcon breaker files (courtesy of Lo�c Boussel)
+        00191113.dcm DermaColorLossLess.dcm
+        MxTwinLossLess.dcm RadBWLossLess.dcm
+      * ENH: For version prior to vtkImageViewer2 -r 1.19
+      * FIX: avoid pb with xmedcon-breaker CT McTwin Elscint images
+
+2003-10-27  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * Removal of ido stuff in CMakeLists.txt
+                                               
+2003-10-24  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * ENH: vtkGdcmReader.cxx can now read multiframe dicom
+      * FIX: remove a call to ->Modified ... see comments
+      * FIX: vtkgdcmViewer.cxx was writting ASCII file...this is so slooooow !
+      
+2003-10-23  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * FIX: Problem with path for libvtkgdcmPython
+      * ENH: Try adding a search script for python site-package
+      * RMV: Remove some file from medcon lib that are not necessary
+      * FIX: gdcm/Makefile.am fix for generating ljpg medcon
+      * ENH: CMakeLists.txt now generate 'pygdcm.so' instead of 'libpygdcm.so'
+      * FIX: More pragma disable fro VC++, 
+             I don't think I break something as it is also disable in VTK/ITK.
+        But it fasten debug compilation time.
+            
+2003-10-23 Jean-Pierre Roux
+      * gdcm now deals with 16 Bits Run Length Encoded images
+        (they are compressed as 2 planes images, 
+         one for the high Bytes, the other for low Bytes)
+
+2003-10-22 Jean-Pierre Roux
+      * Now CheckRead takes into account :
+         - the bugged 'Leonardo' Siemens images
+         - the XA images, sent thru the burning VPRO station
+      * add I9000001.dcm, a GE dlx XA image, thru the VEPRO burning station
+       (breaks DicomWorks)
+
+2003-10-22  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * FIX: When copying a Makefile.am to CMakeLists.txt 
+             one should remove the '\'
+        
+2003-10-22 Jean-Pierre Roux
+      * in gdcmData adding a bugged 'Leonardo' Siemens image 
+        (wrong lengths in header)
+        OK with gdcm, KO with the other viewers :-)
+      * add a GE dlx XA image, thru the VEPRO burning station
+        (breaks DicomWorks)
+
+2003-10-21 Jean-Pierre Roux
+      * in gdcmData add the checkvtkgdcmViewer.sh shell script 
+        for a brutal checking of vtkgdcmViewer compliance
+
+2003-10-21 Jean-Pierre Roux
+      * add the files for 'xmedcon' Jpeg Lossless library
+      * call of 'xmedcom' Jpeg Lossles libray (instead of the old LibIDO one)
+
+2003-10-21 Jean-Pierre Roux
+      * 'Compacted Files' (12 Bits Allocate, 12 Bits Stored) are now dealt with
+     
+2003-10-21 Jean-Pierre Roux
+      * garbage Siemens 'Leonardo' images dealt with
+        (the patch is easy to remove)
+      * cosmetic changes to avoid warnings
+      
+2003-10-20  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * ENH: vtkgdcmViewer now autoscale color/window level on start-up, 
+        no need to press 'r' now.
+   
+2003-10-20  Jean-Pierre Roux
+      * upgrade of checkRead.sh checkWrite.sh according
+        to new Jpeg Lossless decompressor
+      * add US.3405.1.dcm, a genuine RGB medical file ...
+      * add gdcm-ACR-LibIDO.acr, unnormalized Rectangular LibIDO format image
+      * add CLIP0001-Sequoia-U11.dcm, US 'Clip', from SEQUOIA machine,
+                                                  UNIT 11, Hop Cardio              
+2003-10-15  Jean-Pierre Roux
+      * general anonymisation in gdcmData
+      * adding the 'color files' from
+        http://www.leadtools.com/SDK/Medical/DICOM/ltdc19.htm
+      * adding some well knowed bugged-header images
+      * adding checkRead.sk, checkReadColor.sh, checkWrite.sh,
+        waiting for their inclusion in Python testsuite
+
+2003-10-15  Jean-Pierre Roux
+    * gdcmHeader::gdcmHeader(const char *InFilename, bool exception_on_error)
+      no longer seg faults when file is not found
+
+2003-10-14  Jean-Pierre Roux
+     * Emprovement of reading for Dicom encapsulated Jpeg LossLess 
+       MultiFrame images
+
+2003-10-14  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * TODO: *.in file to genereate a UseGDCM later
+
+2003-10-14  Jean-Pierre Roux
+     * Some supposed-to-be Dicom Images have no preamble.
+        OpenFile takes it into account
+     * Jpeg LossLess 24 Bits images doesn't break any longer gdcm
+     * Missing elements added in dicomV3.dic
+      (just to be affraid : have a look at
+       ftp://medical.nema.org/medical/dicom/2003/01v03dif/01v03_06.pdf
+       and do it again next year ;->
+
+2003-10-13  Jean-Pierre Roux
+     * According to PS 3.3-2003 C.11.1.1.2 p 619, when each pixel of 
+       a PALETTE COLOR is stored on 2 Bytes, theese 2 Bytes must be equal.
+       But there are NOT. It's fixed !
+       
+2003-10-13  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * FIX: "jpeglib.h" was not found on VC++
+     * FIX: vtkgdcm was not being installed 
+         
+2003-10-10  Jean-Pierre Roux
+     * ENH : OpenFile closes the file if it *really* doesn't look like
+             an ACR-NEMA / DICOM one.
+     * FIX : testWrite no longer writes an empty file if the source file     
+             is not gdcm Readable
+     * ENH : One more JPEG LossLess type "JPEG Baseline (Process 14)" 
+             is now decoded.
+        
+2003-10-10  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * FIX: CMake generate now documentation
+     * ENH: out of source doc build !
+     * ENH: Generate both user and dev documentation
+     * ENH: Should work on windows too
+     * ENH: Only one doxygen config.in file is needed 
+     * FIX: make install should be ok now on Unix plateform
+     * FIX: PATH to dictionary was wrong (missing /)
+     * ENH: OpenFile, return true if the file looks like an ACR or DICOM file 
+                     
+2003-10-09  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * vtkGdcmReader is now able to read rgb dicom file.
+     * src/gdcmHeaderHelper : GetNumberOfScalarComponents()
+     * added a gdcmViewer to vtk test, use mouse to control 
+        window level & window width
+
+2003-10-09  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * CMake-ification of gdcm, we have now two build system
+     * FIX: on cygwin Wsock32 doesn't exist
+     * FIX: force jpeg dir to the local one (gdcm/src/jpeg)
+     
+2003-10-06  Emanuel Ollart
+     * FIX : compilation process wad broken.
+             Changed gdcmViewer_sources to vtkgdcmViewer_sources
+        
+2003-10-06  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+     * change gdcmViewer -> vtkgdcmViewer
+     * change GetXSpacing and GetYSpacing "%f\\%" is parsed backward
+     
+2003-10-06  Jean-Pierre Roux
+     * FIX :A few nasty patches to allow the reading of a lot of nasty images
+           ( e.g : well known GE images with a wrong elem length,
+                 : Philips MRI Images with a wrong Huffman table)
+      * still to be done : allow the reading of bugged LEONARDO Siemens images
+
+2003-10-03 Jean-Pierre Roux
+      * Odd length strings are padded with '\0' (not with spaces, 
+        to remain compliant with already defined strings, 
+        like Transfert Syntax UID and others)
+
+2003-10-03 Jean-Pierre Roux
+      * ENH :gdcmHeaderHelper::GetNumberOfScalarComponents() added, 
+             to allow displaying RGB images (not only by affim ;-)
+        
+2003-10-03  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * vtkGdcmReader is now able to read rgb dicom file.
+      * src/gdcmHeaderHelper : GetNumberOfScalarComponents()
+
+2003-10-03 Jean-Pierre Roux
+      * A few nasty patches to allow the reading of a lot of nasty images
+        ( e.g : well known GE images with a wrong elem length,
+              : Philips MRI Images with a wrong Huffman table)
+      * still to be done : allow the reading of bugged LEONARDO Siemens images
+
+2003-10-03 Jean-Pierre Roux
+      * One more JPEG LossLess type "JPEG Baseline (Process 14)" is now decoded.
+
+2003-10-03 Jean-Pierre Roux
+      * gdcmHeaderHelper::GetNumberOfScalarComponents() added, 
+        to allow displaying RGB images (not only by affim ;-)
+
+2003-10-03 Jean-Pierre Roux
+      * gdcmFile::GetImageDataIntoVector now
+         - deals with MultiFrames MultiFragments Run Length Encoded files
+         - deals with YcBcR (YBR_FULL) files
+         - deals with YBR_YBR_FULL_422 files (they work as RBG files ?!?)
+          WARNING : nothing was checked for YBR_PARTIAL_422, YBR_ICT, 
+                                       YBR_RCT files.
+          (no sample found :-(
+
+2003-10-02  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * src/*.cxx removed pragma thingies to src/gdcmCommon.h
+        Two reasons: - clear things
+                     - third parties acces gdcm through header files, so won't
+                       suffer anymore VC++ complains
+
+2003-09-30  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * add argv[1] in testvtkGdcmReader.cxx
+      * removed leaks
+
+2003-09-24 Jean-Pierre Roux
+      * The lines are now eigthy characters long for 
+        gdcmHeader.cxx gdcmHeaderHelper.cxx gdcmParse.cxx 
+
+2003-09-22  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * src/gdcmUtil.[cxx|h] : change the _CreateCleanString return value from
+        char* to std::string. Thus, the use of strdup becomes useless. (see
+        previous commis of Malaterre)
+      * src/gdcmElValSet.cxx : reuse commented call to _CreateCleanString like
+        before the last Malaterre's commit.
+
+2003-09-19  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * This commit should fix the Debug building under VC++, the problem
+        was mainly a mixture of debug and release lib being loaded at startup.
+      * I also remove a depency to a specific C function: strdup. Because I had
+        to force the link to msvcrtd (whereas strdup is in libc).
+
+2003-09-16  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * "gdcm::Unfound" string changed to a constant variable (GDCM_UNFOUND)
+        located in the gdcmCommon.h file. All use of reference of tha has been
+        changed to now use the variable GDCM_UNFOUND.
+
+2003-09-16  Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with JPR
+      * Cosmetic changes:
+        - gdcmPython/testSuite.py adapted to the JPR updated Dicts/dicomV3.dic
+          Dicom dictionary. The test suite can now be run again. Note:
+          I'm note very happy with the " (RET)" changes. I believe this
+          RETAINED comment should be dropped when parsing the dictionary.
+        - PACKAGER corrected
+        - DEVELOPPER added.
+        - AUTHORS updated and now in alphabetical order
+      * Makefile.am now exports gdcm.dsw for Windoze users.
+
+2003-09-11  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * cygwin complains about missing std:: in subdir Test/
+
+2003-09-10  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * remove some methods that are now in gdcmHeaderHelper
+
+2003-09-10  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * vtkGdcmReader set spacing and origin correctly
+
+2003-09-09  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * Fix a few delete/delete[] mismatch
+
+2003-09-08  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * src/gdcmHeaderHelper.[h cxx]: added new class that provide an
+        interpretation to data given by gdcmHeader. For instance there are
+        heuristics to get informations (look at different places).
+      * it also include a specific class: gdcmSerieHeaderHelper devoted to
+        sorting DICOM images based on different strategies.
+      * modified Makefiles accordingly.
+
+2003-09-05  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * src/*.cxx : added pragma disable 4786/4251 to get rid of ~4300 warning
+        when building in debug mode
+      * vtk/win32/vtkgdcm.dsp : change /MT -> /MD and /MTd -> /MDd to match
+        src/win32/gdcmdll.dsp
+      * vtk/win32/vtkgdcm.dsp : added /nodefaultlib "mscvrt" for debug mode
+
+2003-08-29  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * Corrected a leak in vtkGdcmREader.cxx, the pSource was find thanks
+            to valgrind.
+
+2003-07-29  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * src/win32/libgdcmjpeg12.dsp was not dos format
+      * src/win32/libgdcmjpeg12.dsp : 
+                  libgdcmijpeg12_EXPORTS -> LIBGDCMIJPEG12_EXPORTS
+      * src/win32/gdcmdll.dsp: + /I "..\jpeg\libijg12"
+
+2003-07-29 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * src/gdcmHeader.h : add std:: prefix for stl elements... like others in
+        the file
+      * src/gdcmFile.cxx : bug fix in affectation type
+      * src/jpeg/libijpeg12/jmorecfg12.h : export for windows modified... like
+        in src/jpeg/libijpeg8/jmorecfg8.h (JPR : copy/paste exists !!!)
+      * Modifs of MVSC projects to compile them. Not concerning 2 identic
+        symbols... future problem ?
+
+2003-07-29  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * src/win32/libgdcmijpeg12.dsp was missing
+      * modified gdcm.dsw accordingly
+
+2003-07-28  Mathieu Malaterre  <Mathieu.Malaterre@creatis.insa-lyon.fr>
+      * src/gdcmHeader.cxx : misplaced return 0.; for ACR/NEMA
+
+2003-07-24 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * src/jpeg/libijg12/.cvsignore, jconfig.* : ommited files while last
+        commit of JPR (before his hollidays to facilitate our work).
+      * setup.py : bug fix in code. Modifications made while the last commit
+        of JPR. The code hasn't been tested before the commit... it's so
+        useless to make that (for best programmer that is JPR) !!!
+
+2003-07-08  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * tagged the current version as Version0_3 (i.e. version 0.3)
+
+2003-07-08  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * vtk/testvtkGdcmReader.cxx : remove a symbol that is unused
+      * src/jpeg/libijg8/jmorecfg.h : adding export symbol for windows
+      * *.dsp : modifications to use new libgdcmijpeg8 library
+      * setup.py : bug fix on VTKPATH variable
+      * PACKAGER : adding all concerning windows
+
+2003-07-07  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmElValSet.cxx, gdcmFile.cxx: JPR bug fix, removal of
+        garbage debug code.
+      * TODO, vtk/vtkGdcmReader.cxx: upcoming fixes comments.
+      * gdcmPython/testSuite.py: JPR bug fix, brutal erasement of
+        test suite reported error.
+      * PACKAGER file added (describes what a packager must do when
+        packaging a new release).
+      * MANIFEST.in, now declares jconfig.linux and jconfig.vc
+      * configure.in: upgraded version number to 0.3.0
+      * fixing build of rpm (through rpm -ta):
+        - Doc/Makefile.am exports proper doxygen files
+        - src/jpeg/libijg8/Makefile.am exports the include files.
+
+2003-07-07  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * vtk/vtkGdcmReader.cxx : bug fix when loading only 1 file.
+      * src/gdcmHeader.h : formatting code
+
+2003-07-07  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * vtk/vtkGdcmReader.[cxx|h] : bug fix when loading only one file.
+        We were obtaining error message from vtk. Now, creation of file list
+        is made in an internal list to prevent this problem.
+        Bug fix when output is empty.
+        Bug fix in update of progress value. Previous commit for this was a bad
+        correction.
+      * vtk/vtkGdcmReader.h : adding comments for InternalFileNaleList variable
+
+2003-07-04  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * src/gdcmHeader.h : added method to get the file name
+      * vtk/vtkGdcmReader.[cxx|h] : bug fix concerning loading of bad dicom
+        files. Added method to remove all files on the input
+        Added FIXME comment concerning the bad parsing of header made by
+        ExecuteInformation method (in ExecuteData method)
+
+2003-07-03  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * vtk/Makefile.am: vtkGdcmReader.h should now be cleany installed
+        when using make instal.
+      * src/gdcmFile.cxx : bug fix under Window after JPR commit
+        RQ : the JPR doesn't appear in the ChangeLog... normal for him
+
+2003-07-03  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * setup.py : adding include dir of jpeg lib to compile all sources
+      * */Win32/*.dsp : JPR fix for windows compilation
+
+2003-07-02  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * src/jpeg/libijg8/jconfig.* : JPR bug fix : now compile on both
+        linux and WINDOWS !
+      * src/gdcmJpeg.cxx : JPR bug fix : erroneous include
+      * src/win32/gdcmdll.dsp : JPR fix for windows compilation
+
+2003-07-02  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * setup.py is again effective on un*x (takes into account the
+        addon of the jpeg library)
+      * Doc/DoxyDevelInstal.txt added (developper's raw documentation)
+      * Doc/Doxy* updated (includes above enhancements)
+      * INSTALL now points to web documentation
+
+2003-07-01  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader.h doesn't make unnecessary reference to
+        gdcmUtil.h anymore.
+      * gdcmPython/Makefile.am now avoids calling the wrappers for the
+        clean target.
+      * src/gdcm*.[cxx|h] :
+        - to allow compilation with gcc 3.x
+          -- clean up of STL usage (added explicit usage of std::)
+          -- small fixes on exceptions.
+          Note: linking not tested !
+        - clean of doxygen comments to avoid warnings at documentation
+          building stage.
+      * vtk/vtkGdcmReader.cxx: g++ warning message clean up (platform
+        dependent convertion).
+
+2003-06-20  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * Clean up of previous JPR garbage commit (not even commented in the
+        Changelog):
+        - Test/Makefile.am removed the reference to unexisting testTS.cxx
+        - moved all jpeg related files from src to src/jpeg/libijg8, with
+          addition/modification of Makefile.am and configure.in.
+        - the testSuite is still brain damage (not guilty).
+
+2003-06-02  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * WrapVTK.py : modifications to get correctly vtk source files to
+        compile
+      * vtk/vtkGdcmReader.cxx : modification for an already existing name
+        (FileName -> Filename)
+
+2003-06-11  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * vtk/vtkGdcmReader.[cxx/h]:
+        - UpdateProgress method should now be effective
+        - removed the limitation on having only images loaded (as opposed
+          to volumes),
+        - when building a stack of images/volume, a lesser number of
+          gdcmHeader and gdcmFile instances should be used (hopefully
+          accelerating things).
+        - when building a stack of images/volumes, files which are not
+          loadable (wrong path-filename, wrong permissions on existing file,
+          or file not parsable by gdcm) are replaced with a black image
+          in the stack (for the caller to notice the problem).
+
+2003-06-03  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * vtk/vtkGdcmReader.cxx: hopefully corrected Z extent.
+
+2003-06-02  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * vtk/vtkGdcmReader[cxx|h] : makes correct code to remove conflicts
+        between standard library (std) and vtk library (problems are found
+        under Windows... thanks Windows !)
+
+2003-05-30  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * vtk/vtkGdcmReader[cxx|h] should now be volume aware (read ready for
+        debug stage).
+      * gdcmPython/demo/vtkGdcmReader.py: commented lines for volume test
+
+2003-05-29  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * vtk/vtkGdcmReader[cxx|h] preparation addons for loading volumes.
+
+2003-05-28  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * When compiling with distutils (see setup.py) the C++ compiler is
+        called with different flags than the default ones (with automake).
+        In order to fix all those warning, I compiled gdcm with the command
+           make 'CXXFLAGS=-Wall -Wstrict-prototypes -D__STDC_LIMIT_MACROS'
+        and went for warning fixes:
+        - src/gdcmHeader.cxx, Test/dcm2acr.cxx, pourFindTaggs.cxx cleaned
+          up from unused variables.
+        - vtk/vtkGdcmReader.cxx: potential bug fix.
+      * src/gdcmHeader.h: Doxygen warning cleanup
+
+2003-05-27  Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * gdcmPython/gdcm.i:
+        - typemaps correction to take into account the systematic replacement
+          of "using namespace std" with std:: prefix e.g. std::list,
+          std::string... (cf changes of 2003-05-21).
+        - gdcmGlob global variable of type gdcmGlobal (defined in
+          src/gdcmUtil.cxx and declared in gdcmPython/gdcm.i) is now
+          exported to Python a as cvar.
+      * gdcmPython/__init__.py now defines two functions GetPubDictTagNames()
+        and GetPubDictTagNamesByCategory() as a replacement for deprecated
+        gdcmDictSet.GetPubDictTagNames() and
+        gdcmDictSet.GetPubDictTagNamesByCategory() class functions (i.e.
+        C++ static methods).
+      * gdcmPython/demo/printGroupedPublicDict.py is operational again,
+        with the above changes.
+
+2003-05-22  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * setup.py, manifest.in : bug fix under linux
+
+2003-05-22  Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * Modification of setup.py to compile vtk part too. Then, we have 2
+        wrappers which must work with same distutils. For that, we have a
+        generic distutils in distusiltsWrapping.py ; with :
+         - build_extWrap class to wrap generically all extensions,
+         - ExtensionWrap base class for all wrapping extension that contains
+           a wrapper
+         - Wrapper interface which wrap sources
+        + In WrapSwig.py  we have extension and wrapper for Swig
+        + In WrapVTK.py  we have extension and wrapper for VTK
+      * MANIFEST.in : modifications to consider vtk directory and new python
+        files for compilation
+
+2003-05-21  Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with Benoit Regrain
+      * Added python wrappers of vtkGdcmReader vtk class (see the
+        source in vtk/vtkGdcmReader.cxx) :
+        - vtk/Makefile.am now builds a library
+        - gdcmPython/Makefile.am now builds vtkgdcmPython a second import
+          python library (as opposed to _gdcm.so wich are the python
+          wrappers of gdcm). vtkgdcmPython.so uses the vtk python wrappers
+          (vtkWrapPython and vtkWrapPythonInit utility) to build vtkgdcmPython
+          import library.
+        - configure.in has an additional flag --enable-vtk that needs
+          to be set to enable compilation of vtk related code, that is:
+          + vtk/vtkGdcmReader.so and
+          + vtk/testvtkGdcmReader C++ demo of vtk wrappers of gdcm)
+          + gdcmPython/vtkgdcmPython.so (see above)
+        - gdcmPython/demo/vtkGdcmDemo.py corrected (some images cannot
+          be read when compressed or when HighBit + 1 != BitsStored),
+        - gdcmPython/demo/vtkGdcmReader.py added. This demo illustrates
+          the usage of the python wrapper of vtkGdcmReader vtk class.
+      * vtk/vtkGdcmReader.cxx: bug fixed (thanks to Benoit Regrain).
+      * src/*.[h] all occurences of stl classes are now prefixed with
+        std::, and all occurences of "using namespace std;" where removed.
+        This is to avoid pollution of global namespace in included files.
+        Apparently vtk does not avoid this pitfall: when using both
+        gdcm and vtk (as in vtk/vtkGdcmReader.cxx) this ended up in a
+        collision of various stl members (principally cout...).
+      * gdcmPython/testSuite.py now cleanly removes temprory generated
+        file.
+      * gdcmPython/gdcm.i now declares a typemap for std::string (to
+        comply with above changes)
+
+2003-05-12  Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with JPR
+      * src/gdcmHeader>[h/cxx] added gdcmHeader::GetPixelSize()
+      * vtk/vtkGdcmReader.cxx now properly inports the image in the
+        vtk data structure (an image Flip was required).
+      * vtk/testvtkGdcmReader.cxx refers to gdcmData subdir instead of Data.
+      * cosmetic changes in documentation.
+
+2003-05-7  Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with JPR
+      * src/gdcmHeader.cxx: the constructor no longer exits when an
+        unexisting file is given as argument.
+      * The subdirectory Data (containing all the images used for the
+        test suite) is not part of this repository anymore. A new module
+        containing those images is now available at
+          :pserver:xxx@cvs.creatis.insa-lyon.fr:2402/cvs/public
+        with the name gdcmData.
+        All the python scripts (including the package initialisation file
+        gdcmPython/__init__.py) were adapated to take this change into
+        account (basically GDCM_DATA_PATH is now GDCM_TEST_DATA_PATH).
+
+2003-05-5  Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with JPR
+      * vtk subdir added. Contains vtkGdcmReader.[cxx|h] a vtk class
+        inherinting from vtkImageReader and testvtkGdcmReader.cxx a small
+        demo of the usage of this class.
+        Compilation of this vtk part is only done when using the --enable-vtk
+        at configure (or autogen.sh) stage.
+
+2003-04-16  Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with JPR
+      * More memory link related corrections and documentation fixes.
+        Notes on valgrind:
+          - maximum info is obtained with a command of the form:
+            valgrind --leak-check=yes --leak-resolution=high --num-callers=40
+                     --show-reachable=yes PrintHeader
+          - the remaining reachable blocks seem to come from the STL
+            allocation scheme through the usage of map and list. It looks
+            like this memory cannot be freed but it is not a memory leak
+            (in fact further invocation to the STL would recollect the
+             unused memory allthough it cannot explicitely be freed).
+      * gdcmPython/demo/vtkGdcmDemo.py added: this is a small demo
+        of displaying an image parsed with gdcm and displayed with VTK.
+        Note: some images don't seem to work e.g.
+            python vtkGdcmDemo.py  ../../Data/US-RGB-8-esopecho.dcm
+      * src/gdcmHeader.x: dicom_vr and Dicts are not class members anymore.
+        Allthough this weakens the semantics, it is a ditch attempt to
+        make gdcm more thread friendly.
+
+2003-04-15  Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with JPR
+      * Memory link hunt (by using valgrind through the command
+          valgrind --show-reachable=yes --leak-check=yes PrintHeader).
+        - added src/gdcmVR.cxx gdcmVR.h that objectify the previous
+          gdcmHeader::_dicom_vr.
+        - gdcmHeader::InitVRDict transfered as gdcmVR::gdcmVR().
+        - gdcmHeader::dicom_vr is now of type gdcmVR* as opposed to
+          VRHT*.
+        - gdcmGlobal global object contained class added (see src/gdcmUtil.x)
+
+2003-04-9  Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with JPR
+      * src/Makefile.am now exports all the necessary include files at
+        make install stage.
+
+2003-04-9 JPR
+      * UpdateGroupLength replaced by new one
+
+2003-04-7 JPR
+      * UpdateGroupLength re-written using H-Table
+        (named UpdateGroupLengthNew untill checks are over)
+
+2003-04-7 Eric Boix <Eric.Boix@creatis.insa-lyon.fr> with JPR
+      * Data/im_00001 renamed to gdcm-MR-PHILIPS-16-Multi-Seq.dcm
+      * gdcmPython/testSuite.py now include a test of gdcmFile::Write.
+      * src:
+        - gdcmHeader::GetPubElValSet removed.
+        - gdcmElValSet::WriteDcm, WriteAcr, WriteExplVR, revamped to
+          UpdateGroupLength, WriteElements, Write.
+        - gdcmHeader::FileType moved to gdcmCommon.h. The enum FileType
+          doesn't contain TrueDicom anymore since ExplicitVR and ImplicitVR
+          carried the same semantics.
+          - src/gdcmHeaderIdo.cxx changed accordingly.
+        - gdcmFile::WriteBase now regroups all the codes from previous
+          versions of WriteDcm, WriteDcmImplVR, and WriteACR.
+        - enum FileType moved to gdcmCommon.h
+      * src/gdcmHeader.cxx AddDefault trashed
+      * gdcmGetXSize added
+      * getimageDataSize now calls gdcmGetXSize
+      * Test/*.cxx changed to agree with above changes
+
+2003-03-31 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader.h: LoadElements() is not a public method anymore
+        (to avoid double call by end user).
+      * Test/*.cxx LoadElements() doesn't need to be called explicitely
+        by end user, since gdcmHeader::gdcmHeader now handles it.
+
+2003-03-29 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * gdcm/Doc many doxygen changes:
+        - Doxyfile now has two different versions, DoxyfileUsers that generates
+          the html.users end users oriented documentation and
+          DoxyfileDeveloppers that generates the html.developper developper
+          oriented documentation.
+        - README changed accordingly
+        - requirement.txt removed (old design info moved to TODO).
+        - Additional files DoxyInstallation.txt, DoxyIntroduction.txt,
+          DoxyMainPage.txt, DoxyPython.txt provide more information.
+        - Note: the website http://www.creatis.insa-lyon.fr/Public/Gdcm/ can now
+          be updated by simply regenerating the docs with doxygen and copying
+          html.developper and html.users to tux:/home/httpd/html/Public/Gdcm
+      * src/gdcmElValSet.cxx: stl <map>.count() can only return 0 or 1. Hence
+        all the tests in the form "if (<map>.count() >1)" were removed.
+      * src/gdcmFile.cxx: cosmetic changes to avoid messages of doxygen about
+        ill-formed documentation sections.
+      * src/gdcmHeader.cxx: ditto
+
+2003-03-27 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * setup.py fixed for un*x (needed macro for stdint.h)
+      * Test/test.cxx renamed to PrintHeader.cxx to avoid collision on
+        un*ces with sh-utils test utility.
+      * gdcmPython/demo/test.py renamed to PrintHeader.py
+      * gdcmPython/demo/ReorganiseFiles.py new demo script added.
+      * gdcmPython/win32/gdcmpycomplet.dsp renamed to gdcmpyembedded.dsp.
+      * gdcmPython/win32/gdcmpy.dsp trashed away (brain damaged).
+      * src/gdcm*.cxx JPR's bad inclusion fixed.
+
+2003-03-26 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader[h, cxx] gdcmHeader now has an IsReadable predicate.
+      * gdcmPython/demo/test.py changed accordingly.
+
+2003-03-25 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * gdcmPython/Makefile.am fixed linking against libstdc++
+      * gdcmPython/_gdcm.so symbolic link to gdcmPython/.libs/pygdcm.so added.
+      * Swig subdir (historical tests of swig version 1.3.17++) removed
+      * Test/testChangeEntete.cxx some lines commented out in order to make
+        compilation work.
+      * src/gdcmHeader.cxx cleaned up wild JPR's dirty kludge.
+      * src/gdcmElValSet.cxx cleaned up frog's forgotten debug message
+
+2003-03-24 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader.cxx gdcmHeader::gdcmHeader now calls LoadElements(),
+        hence the user doesn't need this explicit call.
+        - gdcmPython/testSuite.py, gdcmPython/demo/*.py changed accordingly
+          i.e. LoadElements() call removed.
+      * src/gdcmCommon.h now defines UINT32_MAX (see stdint.h).
+        - src/Makefile.am declares the proper flag for g++.
+      * src/gdcmElValSet.h added gdcmElValSet::GenerateFreeTagKeyInGroup
+        for adding user defined new tags.
+        - src/gdcmHeader.cxx gdcmHeader::NewManualElValToPubDict added.
+        - src/gdcmHeader.cxx gdcmHeader::AddAndDefaultElements now
+          cleanly adds some gdcm added tags (like gdcmXSize, gdcmYSize...)
+
+2003-03-17 Fabrice Bellet <Fabrice.Bellet@creatis.insa-lyon.fr>
+      * Makefile.am, acinclude.m4, configure.in, python.m4, Dicts/Makefile.am,
+        Doc/Makefile.am, Test/Makefile.am, gdcmPython/Makefile.am,
+        src/Makefile.am : the project should properly compile and install
+        with the autotools, included the python wrappers part.
+      * gdcm.spec.in : added a spec file for RPM packaging.
+
+2003-03-14 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * src/gdcmUtils.cxx : redifinition of defaults parameters in code
+
+2003-03-12 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * gdcmPython/__init__.py fix of GDCM_DICT_PATH which was not
+        to exported to the environement (see gdcmPython/testSuite.py
+        for usage).
+      * src/gdcmElValSet.[cxx/h], gdcmElValue.[cxx/h], gdcmFile.[cxx/h],
+        gdcmHeader.[cxx/h]: ElValSet class renamed to gdcmElValSet, and
+        ElValue class renamed to gdcmElValue for obvious consistency reasons.
+      * src/gdcmElValSet.cxx, src/gdcmUtil.[cxx-h] Tokenize utility function
+        moved away from gdcmElValSet.cxx to gdcmUtil.cxx.
+
+2003-03-10 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * gdcmPython/__init__.py doesn't crash anymore when running in
+        in InstallMode or PreInstallMode but with an environment given
+        value of GDCM_DICT_PATH.
+      * src/gdcmDictSet.[cxx/h] coding style.
+
+2003-03-06 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader.h and gdcmHeader.cxx Coding style + doxigenation.
+      * src/gdcm.h general comments moved to TODO, and README
+      * src/gdcm.h should now be seen as a user commodity (including it
+        should suffice to fully use gdcm). It is nowhere including within
+        any of the kernel files src/*.cxx and src/*.h.
+
+2003-03-05 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcm.h splitted in gdcmCommon.h, gdcmDict.h, gdcmDictEntry.h,
+        gdcmDictSet.h, gdcmElValSet.h, gdcmElValue.h, gdcmFile.h,
+        gdcmHeader.h
+      * src/gdcm*.cxx only include their corresponding include file
+        (as opposed to gdcm.h)
+      * gdcmPython/gdcm.i changed accordingly
+      * Test/Makefile.am corrected and added NEWS, AUTHORS in order for
+        the autogen.sh generated "make snapshot" command to work.
+      * autogen.sh removed history related references to crea package.
+
+2003-03-04 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * distutilsSwigCPlusPlus.py work around some swig portability
+        bug.
+
+2003-03-03 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * Eventually, python/gdcmPython was renamed to gdcmPython. This
+        was done in a last ditch attempt to get setup.py _really_
+        operationnal. The python/gdcmPython layaout add the advantage
+        of hidding away the python related distutils specific files
+        (MANIFEST.in, setup.py, distutils*.py...) from the main directory.
+        Alas, the src directory was out of scope (i.e. it's relative
+        position to setup.py was ../src) which made things impossible to
+        handle (see previous version of python/setup.py). Crossing fingers...
+
+2003-02-20 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * python/setup.py now works on Un*x. (harder than I thougth)
+      * python/distutilsSwigCPlusPlus.py can now have include files
+        among the list of sources.
+
+2003-02-20 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * src/gdcmHeader.cxx : bug fix - opening dicom file in binary !!!
+      * modifications in MSVC projects
+
+2003-02-19 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * As stated by the first lines of Test/ExceptionAndPython/README, it
+        looks like we can move back to original usage of exception within
+        src/gdcm* and hence remove the errno stuff that was introduced
+        as a quick and dirty fixture of this problem (added to the TODO).
+      * Doc/Doxyfile configuration file for Doxygen and corresponding
+        README file for usage added.
+      * Test/testWrite.cxx added. This new test comes from a split of
+        test.cxx that is now reverted to its original purpous i.e.
+        testing the proper parsing of a Dicom related file.
+        testWrite.cxx concentrates on testing the IO part of gdcm.
+      * Test/bug1.cxx (containing a bug on WIn32) added.
+      * src/gdcm.h, gdcmHeader.cxx, gdcmDictSet.cxx:
+        - gdcmHeader::GetPubTagNames and  gdcmHeader::GetPubTagNamesByCategory
+          whose purpose is to publish the content of the TagNames of the
+          Dicom public dictionary were not accessible without an
+          instance of class gdcmHeader.
+        - those methods are now static methods of gdcmDictSet and hence
+          require no instances at all to be invocated.
+        - within gdcmDictSet this change required to change some method
+          to class methods (i.e. are now static) among which SetDictPath
+          (renamed to BuildDictPath) and LoadDefaultPubDict.
+      * python/gdcmPython/demo/printGroupedPublicDict.py changed to illustrate
+        the above changes by calling the new method classes of gdcmDictSet.
+      * python/gdcmPython/__init__.py now exposes gdcm.gdcmDictSet for
+        the above to be effective.
+      * python/gdcmPython: in order to wrap properly the above changes
+        for Python, swig version now needs to be > 1.3.17.
+      * python/gdcmPython/Makefile fixed to adapt itself to new
+        configure/make shema introduced by Johan Montagnat (thanks for the
+        contribution). Alas this Makefile cannot be turned into a proper
+        Makefile.am without some heavy changes in the configure.in
+        (for python dectection).
+      * python/gdcmPython/gdcm.i: the out typemap map<string, list<string>>*
+        now avoids publishing the empty entries.
+
+2003-02-13 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * python/setup.py : bug fix concerning install under windows
+        ExtraPath reused :-P
+      * gdcm.dsw : bug fix concerning path for libraries for python !!!
+
+2003-02-13 Benoit Regrain <Benoit.Regrain@creatis.insa-lyon.fr>
+      * Dicts/dicomV3.dic : remove double spaces !!!
+      * src/gdcmElValSet.cxx : bug fix concerning windows compiler
+      * python/gdcmPython/win32/gdcmpycomplet.dsp : bug fix concerning paths
+        and links
+
+2003-01-28 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader.cxx added a post header parsing AddAndDefaultElements
+        method. Doxygenation.
+      * src/gdcm.h clean up of JPR spurious comments.
+
+2003-01-17 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * python/distutilsSwigCPlusPlus.py now properly collects the
+        shadow classes generated by "swig -c++" (gdcm.py in our case)
+        when using "python setup.py install".
+      * python/gdcmPython/__init__.py imports gdcm.py and only manually
+        reexports the working classes.
+      * src/gdcmHeader.cxx all the try/catch/throw calls were replaced
+        by the classical C errno scheme. This is to prevent an obscure
+        behavior of the python wrappers when importing wxPython.wx prior
+        to gdcmPython (which ended up in an abort call). An illustration
+        of this oddity can be found in the Test/ExceptionAndPython
+        subdir (see the README file). This problem probably due to
+        an combination of g++ and dynamic loading.
+      * added Test/ExceptionAndPython (see above)
+
+2003-01-17 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * Changed the layout of the python part to avoid bloating main
+        directory with setup.py, distutilsSwigCPlusPlus.py, MANIFEST.in
+        i.e. the distutils arsenal. All the python related stuff is
+        again in a python subdir, but the package itself is now in
+        python/gdcmPython.
+      * setup.py was cleaned up:
+        - pythonIncludePath removed
+        - python setup.py bdist target is now functional.
+      * gdcmPython/__init__.py doesn't export FileName any more (to avoid
+        collision with other packages). gdcmPython/demo/*.py changed
+        accordingly.
+
+2003-01-15 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * python subdir moved to gdcmPython (preparation of distutils packaging).
+      * gdcmPython/setup.py and distutilsSwigCPlusPlus.py added. The
+        distutils installer is operational.
+      * - gdcmPython/__init__.py now properly loads the swig generated
+          shadow classes (from gdcm.py).
+        - gdcmPython/demo/*.py changed to import the package gdcmPython
+          instead of gdcmPython/demo/load.py.
+        - gdcmPython/testSuite.py changed to import the package gdcmPython.
+
+2002-12-16 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcm.h, src/gdcmHeader.cxx: added GetPubTagNames() resp.
+        GetPubTagNamesByCategory() to gdcmHeader that return a list of the
+        entries within the associated public Dicom dictionary resp. the same
+        information but sorted by the fourth field (PAT, IMG, DIR) of the
+        dictionary.
+        - Dicts/dicomV3.dic Entries which had an unspecified fourth field
+          are now in the "???" group.
+        - python/gdcm.i changed accordingly,
+        - python/demo/printGroupedPublicDict.py added, that gives an example
+          of the above new functionalities in Python.
+
+2002-12-11 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcm.h, gdcmHeader.cxx:
+        - historic references to glib's g_malloc and g_free (#defined)
+          were definitively removed.
+        - gdcm.h: cosmetic changes (part of comments moved to Doc/requirements)
+      * src/gdcmElValSet.cxx:
+        - GetElement(guint32, guint32) renamed to GetElementByNumber.
+        - GetElValue(guint32, guint32) renamed to GetElValueByNumber.
+        - GetElValue(string) renamed to GetElValueByName.
+        - Added GetElementByName(string).
+      * src/gdcmHeader.cxx: added
+        - GetPubElValRepByNumber(guint16, guint16)
+        - GetPubElValRepByName(string)
+        - GetShaElValRepByNumber(guint16, guint16)
+        - GetShaElValRepByName(string)
+        - GetShaElValByNumber(guint16, guint16)
+        - GetShaElValRepByName(string)
+        - GetElValRepByNumber(guint16, guint16)
+        - GetElValRepByName(string)
+        - GetElValByNumber(guint16, guint16)
+        - GetElValRepByName(string)
+      * Doc/requirements.txt added.
+
+2002-12-9 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * Test/Makefile building now depends on the one of libgdcm.so
+      * src/gdcmHeader.cxx and gdcm.h are now OB (undefined length encoded
+        pixel data) aware which enables finding the address (offset) of
+        the pixel data of JPEG encoded DICOM files. This leaves only a single
+        file in the testSuite whose pixel data address (offset) is unknown.
+      * python/testSuite.py changed accordingly.
+
+2002-12-6 Christophe Odet + Hugues Benoit-Cattin + Eric.Boix
+      * VC++ has some strong limitations when working with the STL, as stated
+        in http://support.microsoft.com/support/kb/articles/Q168/9/58.ASP :
+             "Also note that some STL containers (map, set, queue, list, deque)
+              cannot be exported. [...]
+              Some STL classes contain nested classes. These classes can not
+              be exported. [...]
+              This is caused by a designed limitation that once a template
+              class is instantiated, it can not be re-instantiated and
+              exported."
+        Since our usage of map<> is ubiquitous in gdcm, this "designed
+        limitation" of VC++ is a pitfall.
+        Hence the Python wrappers of gdcm cannot be incrementally linked
+        against the c++ dynamic library. The dirty but only workaround is
+        to forget about incremental link of dynamic libraries and to generate
+        the Python wrappers library with the inclusions of the underlying C++
+        library.
+        The following modifications concern this matter on Win32/VC++:
+      - wrapping python correct with standalone wrapped dll (don't use separate
+         dll under windows !!!!)
+      - python21_d debug mode enabled (ask Frog how to use it :-)
+      - NO problem with having an STL member of class for example string in C++
+        WITH THE RESTRICTION OF FORGETING ABOUT INCREMENTAL LINK.
+      - Python test of dcmlib in Python is ok under windows on a large set
+        (one) of image(s).
+      * removed glib references
+      * typedef's inserted in gdcm.i for correct swig type management
+
+2002-11-27 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * python/demo/*.py load.py extracted from test.py. Added explore.py
+        that only displays required tags and testAll.py that parses all
+        the files of the testsuite without using unittest.
+      * python/testSuite.py other additional test on new files added.
+      * Data/* new test files added accordingly to the testSuite.
+      * src/gdcmHeader.cxx avoid overwriting of the dictionary when
+        the vr in the file differs from the one of the dictionary.
+
+2002-11-20 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcm.h and gdcmHeader.cxx gdcm no longer loads all the elements
+        values, but limits itself to values which are below a user specified
+        size (by default 1024 bytes).
+      * python/gdcm.i : elements not loaded (because their size is above the
+        user specified treshold) are exported with their TagKey as key of the
+        python dictionary. This enables the testsuite to make some checks
+        on the unloaded elements (since we have their offset and size).
+      * python/testSuite.py
+        - now tests for the existence and proper value of the pixel data
+        - two new examples added.
+      * Data/gdcm-MR-SIEMENS-16.acr[12] added.
+
+2002-11-18 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcm.h and gdcmHeader.cxx are now "Big Endian transfer syntax"
+        aware. See the strategy comments in gdcmHeader::FindLength().
+      * Test/test.cxx now accepts a filename as first argument.
+      * Data/US-PAL-8-10x-echo.dcm and US-RGB-8-epicard.dcm added.
+      * python/testSuite.py changed to integrate test on above files.
+
+2002-11-15 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * Dicts/dicomV3.dic removed all the trailing (RET) when the
+        the vr was also RET.
+      * python/testSuite.py more tests added.
+
+2002-11-14 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * python/testSuite.py unittest test suite added (uses Data)
+      * Data/* dcm and acr files for the test suite.
+      * glib dependance removed from un*x version. We now use ISO C99
+        7.18 Integer types (see stdint.h)
+        - python/Makefile, src/Makefile src/gdcm.h
+      * src/ when an explicit vr (like dicom files) suddenly poped an
+        implicit element we use to mark the underlying DictEntry of the
+        concerned ElValue with "Implicit". This strategy was damageable
+        too the public or provite dictionaries, since some of their vr
+        would be changed. Since Header::FindLength heavily relies on the
+        detection by Header::FindVR of falsely explicit elements, I
+        added an extra ImplicitVr member to ElValue (boolean).
+        The rest of the changes we the necessary adaptations.
+
+2002-11-12 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader::FindLength bug fix when trapping falsely explicit
+        VR files.
+      * src/gdcmHeader::FindVR: hard way fix of falsely explicit vr files.
+
+2002-11-8 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * Adaptation for porting to VC++:
+        - src/gdcm.h
+          o forced to use std namespace (for string to be known)
+          o all class use __declspec export style on WIN32
+        - src/gdcmUtil.cxx new Exit method that wraps the exit call
+          (in stdlib.h on Win32 but in std:: for gcc)
+      * src/gdcmDictSet::SetDictPath adds a trailing / to environement
+        variable GDCM_DICT_PATH.
+      * src/gdcmHeader.cxx verbose comments made discrete.
+
+2002-11-7 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * python/gdcm.i: added a typemap that converts a C++ hashing table
+        to native Python dictionary.
+      * python/demo/test.py:
+        - now uses the native dictionary for exploration of gdcmHeader.
+        - takes an optional filename argument (the file to parse).
+      * src/gdcm.h and gdcmHeader.cxx: gdcmHeader now has an accessor on
+        PubElVals hashing table.
+      * Dicts/dicomV3.dic removed error prone trailing spaces.
+
+2002-11-6 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * Python wrapping process moved away from src/Makefile to
+        newly created python/Makefile (as well as gdcm.i)
+      * python/demo/test.py (that mirrors Test/test.cxx) is effective.
+      * src/gdcmHeader::FindLength only looks for current vr when necessary.
+      * src/gdcmDictSet.cxx: the dictionnaries directory path is now imported
+        from the environement variable GDCM_DICT_PATH (when existing).
+      * src/gdcmDict::GetTag bug fix.
+
+2002-10-31 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * Straightforward temporary fixes for swig to build the python wrappers.
+        src/Makefile now has a python working entry [by working we mean
+        that we can import the shadow classes without errors].
+
+2002-10-29 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * hashtest.cxx removed (since already in Test)
+      * src/gdcmlib.h renamed to src/gdcm.h
+      * src/dcm.i renamed to src/gdcm.i
+      * src/Makefile prepared for python wrapping
+
+2002-10-29 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader.cxx :
+        - Parsing of header is now separated from loading of element values
+          (see gdcmHeader::LoadElements).
+        - general clean up of hopefully all file access (creation of
+          ReadInt16 and ReadInt32)
+
+2002-10-22 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader.cxx :
+        - RecupLgr renamed to FindLength and cut off with new IsAnInteger
+          method.
+        - SetLgrElem renamed to SetLength
+        - GetLgrElem renamed to GetLength
+        - ~gdcmHeader() made virtual to pesky warning messages at compile.
+      * src/gdcmElValSet.cxx fixed both GetElValue methods
+      * Dicts/dicomV3.dic falacious entry [7fe0 0010 OT PXL Pixel Data]
+        due to IdoDude was cleaned out.
+
+2002-10-21 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader.cxx RecupLgr split in FindVR and RecupLgr. FindVR
+        concentrates on finding the value representation (when it exists).
+        RecupLgr now only finds the element value length, and it avoids
+        returning the unecessary skL (skipped length).
+        Also, offsetCourant was simply removed (with taille_fich) since
+        it was redundant with the File position internals (by using
+        ftell and fseek). This also made skL (see above in RecupLgr) usage
+        jajun.
+      * src/gdcmHeaderIdo.cxx src/gdcmIdo.h added. Those files concentrate
+        on the libido specificities which are handled through class
+        inheritance.
+      * Test/implicit_vr.dcm dicom v3 in implicit value representation
+        added.
+
+2002-10-17 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * Truckload of changes. Parsing of header is barely functional
+        (see Test/test) with the standard dictionary (see Dicts/dicomV3.dic).
+
+2002-10-10 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader.cxx many addons of low level methods
+
+2002-10-07 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * src/gdcmHeader now contains_IdDcmCheckSwap, _IdDcmRecupLgr,
+        and _IdDcmSWAP_LONG.
+
+2002-09-12 Eric Boix <Eric.Boix@creatis.insa-lyon.fr>
+      * This corresponds to all the changes decided at the meeting of
+        May 23 2002. Needless to say we are running late...
+
diff --git a/Utilities/ITK/Utilities/gdcm/DEVELOPPER b/Utilities/ITK/Utilities/gdcm/DEVELOPPER
new file mode 100644
index 0000000000000000000000000000000000000000..b0c1b158bdddf88e00128b59ce084e3b80bf2256
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/DEVELOPPER
@@ -0,0 +1 @@
+The entry point is Doc/Website/Developpers.html
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/.cvsignore b/Utilities/ITK/Utilities/gdcm/Dicts/.cvsignore
new file mode 100644
index 0000000000000000000000000000000000000000..ed951f5ccdf6233e67a50da8a22d364e163382b8
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/.cvsignore
@@ -0,0 +1,5 @@
+Makefile
+Makefile.in
+DartTestfile.txt
+cmake.check_depends
+cmake.depends
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/ACUSON.dic b/Utilities/ITK/Utilities/gdcm/Dicts/ACUSON.dic
new file mode 100644
index 0000000000000000000000000000000000000000..ea805de1fa33d196c68ba094c9cd0918e1171790
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/ACUSON.dic
@@ -0,0 +1,8 @@
+7fdf 0010 LO 1 Private Creator (ACUSON:1.2.840.113680.1.0)
+7fdf 1000 IS 1 Lossy Compression Ratio
+7fdf 1001 US 1 Image Format
+7fdf 1002 US 1 Acuson Region Type
+7fdf 100b UL 1 Acuson Image Apex X
+7fdf 100c UL 1 Acuson Image Apex Y
+7fdf 100d IS 1 B-Color-On Flag
+7fdf fe00 OB 1 Data Padding
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/CMakeLists.txt b/Utilities/ITK/Utilities/gdcm/Dicts/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d7ddb2c07803dcd0bd8aea43f9b7bc6671cab7ba
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/CMakeLists.txt
@@ -0,0 +1,118 @@
+#-----------------------------------------------------------------------------
+# DICOM dictionary stuff
+
+#-----------------------------------------------------------------------------
+# Generate our own 'DICOM' dictionary, based on the following dictionaries:
+SET(ALL_DICTS
+  dicomV3.dic
+  Papyrus.dic
+  NIH.dic     #the forbidden one...
+  SPI.dic
+  #  PHILIPS-Intera.dic # uncomment me if you want
+  )
+
+# Better solution
+SET(TEST_DICT_BODY)
+FOREACH(dict ${ALL_DICTS})
+  # Properly set dependencies, therefore `touch Philips-Intera.dic` does not rebuild
+  # but adding/removing a line in Philips-Intera.dic rebuild as expected
+  CONFIGURE_FILE("${GDCM_SOURCE_DIR}/Dicts/${dict}"
+       "${GDCM_BINARY_DIR}/Dicts/${dict}" COPYONLY IMMEDIATE)
+  FILE(READ "${GDCM_SOURCE_DIR}/Dicts/${dict}" dict_append)
+  SET(TEST_DICT_BODY "${TEST_DICT_BODY}\n${dict_append}")
+ENDFOREACH(dict)
+CONFIGURE_FILE("${GDCM_SOURCE_DIR}/Dicts/gdcm.dic.in"
+  "${GDCM_BINARY_DIR}/Dicts/gdcm.dic" @ONLY IMMEDIATE)
+
+#-----------------------------------------------------------------------------
+# Nice trick to avoid creating a .h file each time we compile gdcm
+# Since CONFIGURE_FILE do a 'copy if different'
+# We have to write the file here since is contains 'DICOM_DICTIONARY'
+# Which is a variable afterward...
+
+# Following code contributing by Andy Cedilnik (Kitware)
+FILE(READ "${GDCM_BINARY_DIR}/Dicts/gdcm.dic" ENT)
+STRING(REGEX REPLACE "\r?\n" ";" ENT "${ENT}")
+SET(DICOM_DATA_DICTIONARY "")
+
+FOREACH(line ${ENT})
+  STRING(REGEX REPLACE
+    "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f]) ([0-9a-f][0-9a-f][0-9a-f][0-9a-f]) ([A-Z]+) ([1-9n-]+) (.*)$"
+    "   {0x\\1, 0x\\2, \"\\3\" , \"\\4\" , \"\\5\"}, " nline "${line}")
+  SET(DICOM_DATA_DICTIONARY "${DICOM_DATA_DICTIONARY}\n${nline}")
+ENDFOREACH(line)
+
+SET(DICOM_DATA_DICTIONARY "${DICOM_DATA_DICTIONARY} \n {0,0,0,0,0}")
+
+#-----------------------------------------------------------------------------
+# ... for DicomTS file
+FILE(READ "dicomTS.dic" ENT_TS)
+STRING(REGEX REPLACE "\r?\n" ";" ENT_TS "${ENT_TS}")
+SET(DICOM_TS_DICTIONARY "")
+
+FOREACH(line ${ENT_TS})
+  STRING(REGEX REPLACE
+    "^([0-9.]+) +(.*)$"
+    "  ts[\"\\1\"] = \"\\2\"; " nline "${line}")
+  SET(DICOM_TS_DICTIONARY "${DICOM_TS_DICTIONARY}\n${nline}")
+ENDFOREACH(line)
+
+#-----------------------------------------------------------------------------
+# ... for DicomVR file
+FILE(READ "dicomVR.dic" ENT_VR)
+STRING(REGEX REPLACE ";" "/" ENT_VR "${ENT_VR}") # CMake doesn't like ';'
+STRING(REGEX REPLACE "\r?\n" ";" ENT_VR "${ENT_VR}")
+SET(DICOM_VR_DICTIONARY "")
+
+FOREACH(line ${ENT_VR})
+  STRING(REGEX REPLACE
+    "^([A-Z][A-Z]) (.*)/ +//.*$"
+    "  vr[\"\\1\"] = \"\\2\"; " nline "${line}")
+  SET(DICOM_VR_DICTIONARY "${DICOM_VR_DICTIONARY}\n${nline}")
+ENDFOREACH(line)
+
+#-----------------------------------------------------------------------------
+# ... for DictGroupName file
+FILE(READ "DictGroupName.dic" ENT_TS)
+STRING(REGEX REPLACE "\r?\n" ";" ENT_TS "${ENT_TS}")
+SET(DICT_GROUP_NAME_DICTIONARY "")
+
+FOREACH(line ${ENT_TS})
+  STRING(REGEX REPLACE
+    "^([0-9a-f]+) +(.*)$"
+    "  groupName[0x\\1] = \\2; " nline "${line}")
+  SET(DICT_GROUP_NAME_DICTIONARY "${DICT_GROUP_NAME_DICTIONARY}\n${nline}")
+ENDFOREACH(line)
+
+#-----------------------------------------------------------------------------
+# ... for DicomDir file
+FILE(READ "DicomDir.dic" ENT_DIR)
+STRING(REGEX REPLACE "\\\\" "\\\\\\\\" ENT_DIR "${ENT_DIR}")
+STRING(REGEX REPLACE ";" "/" ENT_DIR "${ENT_DIR}") # CMake doesn't like ';'
+STRING(REGEX REPLACE "\r?\n" ";" ENT_DIR "${ENT_DIR}")
+SET(DICOM_DIR_DICTIONARY "")
+
+FOREACH(line ${ENT_DIR})
+  STRING(REGEX REPLACE
+    "^(metaElem|patientElem|studyElem|serieElem|imageElem) *([a-f0-9]+) ([a-f0-9]+) [\"](.*)[\"](.*)$"
+    "  {\"\\1\" , 0x\\2 , 0x\\3 , \"\\4\"}, \\5" nline "${line}")
+  SET(DICOM_DIR_DICTIONARY "${DICOM_DIR_DICTIONARY}\n${nline}")
+ENDFOREACH(line)
+
+#-----------------------------------------------------------------------------
+# ... Set the dictionnary
+SET(DICOM_DIR_DICTIONARY "${DICOM_DIR_DICTIONARY} \n {0,0,0,0}")
+
+CONFIGURE_FILE("${GDCM_SOURCE_DIR}/src/gdcmDefaultDicts.cxx.in" 
+  "${GDCM_BINARY_DIR}/src/gdcmDefaultDicts.cxx" IMMEDIATE)
+
+#-----------------------------------------------------------------------------
+INSTALL_FILES(/include/InsightToolkit/gdcm/Dicts .dic
+  dicomV3
+  dicomVR
+  dicomTS
+  DicomDir
+  DictGroupName
+  gdcm
+)
+
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/DicomDir.dic b/Utilities/ITK/Utilities/gdcm/Dicts/DicomDir.dic
new file mode 100644
index 0000000000000000000000000000000000000000..58d480bc605fcfa6294e838d3982c1ac34a3d0ca
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/DicomDir.dic
@@ -0,0 +1,96 @@
+metaElem    0002 0000 "123"                  // Meta Group Length : to be computed later
+metaElem    0002 0001 "\002\000\000\000"     // File Meta Information Version
+metaElem    0002 0002 "1.2.840.10008.1.3.10" // Media Stored SOP Class UID i.e. : 'Media Storage Directory Storage'
+metaElem    0002 0003 ""                     // Media Stored SOP Instance UID  : may be forged later
+metaElem    0002 0010 "1.2.840.10008.1.2.1"  // Transfer Syntax UID i.e. : Explicit VR - Little Endian
+metaElem    0002 0012 ""                     // Implementation Class UID : may be forged later
+metaElem    0002 0013 "gdcmLib "             // Implementation Version Name  don't remove trailing space !
+metaElem    0002 0016 " "                    // Source Application Entity Title (our ?)
+metaElem    0002 0100 ""                     // Private Information Creator
+metaElem    0004 1130 ""                     // File-set ID
+metaElem    0004 1200 "0"                    // Offset of the first dir of root dir entity : to be computed later
+metaElem    0004 1202 "0"                    // Offset of the last  dir of root dir entity : to be computed later
+metaElem    0004 1212 "-1"                   // File-set consistency flag : 0xffff Length inconsistencies will be assumed
+
+patientElem fffe e000 "255"                  // 'no length' item : length to be set to 0xffffffff later
+patientElem 0004 1400 "0"                    // Offset of next directory record : = 0x0 : fffe e00d at end !
+patientElem 0004 1410 "65535"                // Record in use flag : 65535 = 0xFFFF (see 03_10PU.PDF p 31)
+patientElem 0004 1420 "0"                    // Offset of referenced lower-level dir entity : to be computed later
+patientElem 0004 1430 "PATIENT "             // Directory Record Type    don't remove trailing space !
+patientElem 0008 0005 "ISO_IR 100"           // Specific Character Set
+patientElem 0010 0010 ""                     // Patient's Name
+patientElem 0010 0020 ""                     // Patient ID
+patientElem 0010 0030 ""                     // Patient's Birthdate
+patientElem 0010 0040 ""                     // Patient's Sex
+patientElem fffe e00d ""                     // Item delimitation : length to be set to ZERO later
+
+studyElem   fffe e000 "-1"                   // 'no length' item : length to be set to 0xffffffff later
+studyElem   0004 1400 "0"                    // Offset of next directory record : = 0x0 : fffe e00d at end !
+studyElem   0004 1410 "65535"                // Record in use flag : 65535 = 0xFFFF (see 03_10PU.PDF p 31)
+studyElem   0004 1420 "0"                    // Offset of referenced lower-level dir entity : to be computed later
+studyElem   0004 1430 "STUDY "               // Directory Record Type    don't remove trailing space !
+studyElem   0008 0005 "ISO_IR 100"           // Specific Character Set
+studyElem   0008 0020 ""                     // Study Date
+studyElem   0008 0030 ""                     // Study Time
+studyElem   0008 0050 ""                     // Accession Number
+studyElem   0008 1030 ""                     // Study Description
+studyElem   0020 000d ""                     // Study Instance UID : may be forged later
+studyElem   0020 0010 ""                     // Study ID :           may be forged later
+studyElem   fffe e00d ""                     // Item delimitation : length to be set to ZERO later
+
+serieElem   fffe e000 "-1"                   // 'no length' item : length to be set to 0xffffffff later
+serieElem   0004 1400 "0"                    // Offset of next directory record : = 0x0 : fffe e00d at end !
+serieElem   0004 1410 "65535"                // Record in use flag : 65535 = 0xFFFF (see 03_10PU.PDF p 31)
+serieElem   0004 1420 "0"                    // Offset of referenced lower-level dir entity : to be computed later
+serieElem   0004 1430 "SERIES"               // Directory Record Type    don't add trailing space !
+serieElem   0008 0005 "ISO_IR 100"           // Specific Character Set
+serieElem   0008 0021 ""                     // Series Date
+serieElem   0008 0031 ""                     // Series Time
+serieElem   0008 0060 ""                     // Modality
+serieElem   0008 0080 ""                     // Institution Name  :   may be forged later
+serieElem   0008 0081 ""                     // Institution Address : may be forged later
+serieElem   0008 1010 ""                     // Station Name
+serieElem   0008 1050 ""                     // Performing Physician's Name
+serieElem   0008 103e ""                     // Series Description :  may be forged later
+serieElem   0018 1030 ""                     // Protocol Name
+serieElem   0020 000e ""                     // Series Instance UID : may be forged later
+serieElem   0020 0011 "0"                    // Series Number :       may be forged later
+serieElem   fffe e00d ""                     // Item delimitation :   length to be set to ZERO later
+
+imageElem   fffe e000 "-1"                   // 'no length' item : length to be set to 0xffffffff later
+imageElem   0004 1400 "0"                    // Offset of next directory record : = 0x0 : fffe e00d at end !
+imageElem   0004 1410 "65535"                // Record in use flag : 65535 = 0xFFFF (see 03_10PU.PDF p 31)
+imageElem   0004 1420 "0"                    // Offset of referenced lower-level dir entity : to be computed later
+imageElem   0004 1430 "IMAGE "               // Directory Record Type    don't remove trailing space !
+imageElem   0004 1500 ""                     // Referenced File ID : will be set later  =  relative File Name
+imageElem   0004 1510 ""                     // Referenced SOP Class UID in File    : may be forged later
+imageElem   0004 1511 ""                     // Referenced SOP Instance UID in File : may be forged later
+imageElem   0004 1512 ""                     // Referenced Transfer Syntax in File
+imageElem   0008 0005 "ISO_IR 100"           // Specific Character Set
+imageElem   0008 0008 ""                     // Image Type
+imageElem   0008 0016 ""                     // SOP Class UID :    to be set/forged later
+imageElem   0008 0018 ""                     // SOP Instance UID : to be set/forged later
+imageElem   0008 0023 ""                     // Content Date
+imageElem   0008 0033 ""                     // Content Time
+imageElem   0018 1060 "0"                    // Trigger Time
+imageElem   0020 0013 "0"                    // Image Number
+imageElem   0020 0032 "1.0\1.0\1.0 "         // Image Position Patient
+imageElem   0020 0037 "1\0\0\0\1\0 "         // Image Orientation Patient
+imageElem   0020 0052 "0"                    // Frame of Reference UID
+imageElem   0020 1041 "0.0"                  // Slice Location
+imageElem   0020 4000 ""                     // Image Comments
+imageElem   0028 0002 "1"                    // Samples per Pixel
+imageElem   0028 0004 " "                    // Photometric Interpretation
+imageElem   0028 0006 "0"                    // Planar Configuration
+imageElem   0028 0008 "1"                    // Number of Frames
+imageElem   0028 0010 "0"                    // Rows
+imageElem   0028 0011 "0"                    // Columns
+imageElem   0028 0030 "1.0\1.0 "             // Pixel Spacing
+imageElem   0028 0100 " "                    // Bits Allocated
+imageElem   0028 0101 " "                    // Bits Stored
+imageElem   0028 0103 " "                    // Pixel Representation
+imageElem   0028 1052 "0 "                   // Rescale Intercept
+imageElem   0028 1053 "1 "                   // Rescale Slope
+imageElem   0050 0004 "0"                    // Calibration Image
+imageElem   fffe e00d ""                     // Item delimitation : length to be set to ZERO later
+
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/DictGroupName.dic b/Utilities/ITK/Utilities/gdcm/Dicts/DictGroupName.dic
new file mode 100644
index 0000000000000000000000000000000000000000..13278ef88338b3a88ca1d98c7f17c974795b8265
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/DictGroupName.dic
@@ -0,0 +1,62 @@
+0000 "Command"
+0002 "Meta Elements"
+0004 "Directory"
+0008 "Identifing"
+0010 "Patient"
+0012 "Clinical Trial"
+0018 "Acquisition"
+0020 "Relationship"
+0028 "Image Presentation"
+0032 "Study"
+0038 "Visit"
+003a "Waveform"
+0040 "Procedure"
+0050 "Device"
+0054 "Nuclear Medicine"
+2000 "BFS"
+2010 "BFB"
+2020 "BAB"
+2040 "IOB"
+2100 "Print Job"
+2110 "Printer"
+3002 "Radio Therapy"
+3004 "DVH"
+3006 "SSET"
+300a "RT"
+300b "RT"
+300e "Review"
+4000 "Text"
+4008 "Results"
+5000 "Curves"
+5002 "Curves"
+5004 "Curves"
+5006 "Curves"
+5008 "Curves"
+500a "Curves"
+500c "Curves"
+500e "Curves"
+5010 "Curves"
+5012 "Curves"
+5014 "Curves"
+5016 "Curves"
+5018 "Curves"
+501a "Curves"
+501c "Curves"
+501e "Curves"
+6000 "Overlays"
+6002 "Overlays"
+6004 "Overlays"
+6006 "Overlays"
+6008 "Overlays"
+600a "Overlays"
+600c "Overlays"
+600e "Overlays"
+6010 "Overlays"
+6012 "Overlays"
+6014 "Overlays"
+6016 "Overlays"
+6018 "Overlays"
+601a "Overlays"
+601c "Overlays"
+601e "Overlays"
+7fe0 "Pixels"
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/ELSCINT.dic b/Utilities/ITK/Utilities/gdcm/Dicts/ELSCINT.dic
new file mode 100644
index 0000000000000000000000000000000000000000..da46b3f650ddc9fff6897f508a45adedea7fa1b9
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/ELSCINT.dic
@@ -0,0 +1,14 @@
+00e1 0010 LO 1 Implementor ID
+00e1 1022 DS 2 Presentation Relative Center
+00e1 1023 DS 2 Presentation Relative Part
+00e1 1024 CS 1 Presentation Horizontal Invert
+00e1 1025 CS 1 Presentation Vertical Invert
+00e1 1040 SH 1 Image Label
+01f3 0010 LO 1 Implementor ID
+01f3 1011 SQ 1 PS Sequence
+07a1 0010 LO 1 Implementor ID
+07a1 1010 LO 1 Tamar Software Version
+6001 0010 LO 1 Implementor ID
+6001 1010 CS 1 Text Overlay Flag
+00e1 0010 LO 1 Implementor ID
+00e1 1022 DS 2 Presentation Relative Center
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/GE-EchoPAC.dic b/Utilities/ITK/Utilities/gdcm/Dicts/GE-EchoPAC.dic
new file mode 100644
index 0000000000000000000000000000000000000000..08af46f9ce4885860592228db72b7adebeb2eeb5
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/GE-EchoPAC.dic
@@ -0,0 +1,2 @@
+6003 00xx LO 1 Private Creator (GEMS_Ultrasound_ImageGroup_001)
+7FE1 00xx LO 1 Private Creator (GEMS_Ultrasound_MovieGroup_001)
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Advance.dic b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Advance.dic
new file mode 100644
index 0000000000000000000000000000000000000000..95e188d0ad19510cfb29e0eeefa8f796c662d83d
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Advance.dic
@@ -0,0 +1,306 @@
+0009 0010 SH 1 Private Creator Data Element
+0009 1001 LO 2 GE Advance Implementation Version Name
+0009 1002 LO 1 GE Advance Patient.patient_id
+0009 1003 SH 1 GE Advance Patient.compatible_version
+0009 1004 SH 1 GE Advance Patient.software_version
+0009 1005 DT 1 GE Advance Patient.patient_datetime
+0009 1006 SL 1 GE Advance Patient.type
+0009 1007 UI 1 GE Advance Exam.exam_id
+0009 1008 SH 1 GE Advance Exam.compatible_version
+0009 1009 SH 1 GE Advance Exam.software_version
+0009 100a UI 1 GE Advance Scan.scan_id
+0009 100b SH 1 GE Advance Scan.compatible_version
+0009 100c SH 1 GE Advance Scan.software_version
+0009 100d DT 1 GE Advance Scan.scan_datetime
+0009 100e DT 1 GE Advance Scan.scan_ready
+0009 100f UI 1 GE Advance Scan.scan_description
+0009 1010 LO 1 GE Advance Scan.hospital_name
+0009 1011 LO 1 GE Advance Scan.scanner_desc
+0009 1012 LO 1 GE Advance Scan.manufacturer
+0009 1013 UI 1 GE Advance Scan.for_identifier
+0009 1014 LO 1 GE Advance Scan.landmark_name
+0009 1015 SH 1 GE Advance Scan.landmark_abbrev
+0009 1016 SL 1 GE Advance Scan.patient_position
+0009 1017 SL 1 GE Advance Scan.scan_perspective
+0009 1018 SL 1 GE Advance Scan.scan_type
+0009 1019 SL 1 GE Advance Scan.scan_mode
+0009 101a SL 1 GE Advance Scan.start_condition
+0009 101b SL 1 GE Advance Scan.start_cond_data
+0009 101c SL 1 GE Advance Scan.sel_stop_cond
+0009 101d SL 1 GE Advance Scan.sel_stop_cond_data
+0009 101e SL 1 GE Advance Scan.collect_deadtime
+0009 101f SL 1 GE Advance Scan.collect_singles
+0009 1020 SL 1 GE Advance Scan.collect_countrate
+0009 1021 SL 1 GE Advance Scan.countrate_period
+0009 1022 SL 1 GE Advance Scan.delayed_events
+0009 1023 SL 1 GE Advance Scan.delayed_bias
+0009 1024 SL 1 GE Advance Scan.word_size
+0009 1025 SL 1 GE Advance Scan.axial_acceptance
+0009 1026 SL 1 GE Advance Scan.axial_angle_3d
+0009 1027 SL 1 GE Advance Scan.theta_compression
+0009 1028 SL 1 GE Advance Scan.axial_compression
+0009 1029 FL 1 GE Advance Scan.gantry_tilt_angle
+0009 102a SL 1 GE Advance Scan.collimation
+0009 102b SL 1 GE Advance Scan.scan_fov
+0009 102c SL 1 GE Advance Scan.axial_fov
+0009 102d SL 1 GE Advance Scan.event_separation
+0009 102e SL 1 GE Advance Scan.mask_width
+0009 102f SL 1 GE Advance Scan.binning_mode
+0009 1030 SL 1 GE Advance Scan.trig_rej_method
+0009 1031 SL 1 GE Advance Scan.number_for_reject
+0009 1032 SL 1 GE Advance Scan.lower_reject_limit
+0009 1033 SL 1 GE Advance Scan.upper_reject_limit
+0009 1034 SL 1 GE Advance Scan.triggers_acquired
+0009 1035 SL 1 GE Advance Scan.triggers_rejected
+0009 1036 LO 1 GE Advance Scan.tracer_name
+0009 1037 LO 1 GE Advance Scan.batch_description
+0009 1038 FL 1 GE Advance Scan.tracer_activity
+0009 1039 DT 1 GE Advance Scan.meas_datetime
+0009 103a FL 1 GE Advance Scan.pre_inj_volume
+0009 103b DT 1 GE Advance Scan.admin_datetime
+0009 103c FL 1 GE Advance Scan.post_inj_activity
+0009 103d DT 1 GE Advance Scan.post_inj_datetime
+0009 103e SH 1 GE Advance Scan.radionuclide_name
+0009 103f FL 1 GE Advance Scan.half_life
+0009 1040 FL 1 GE Advance Scan.positron_fraction
+0009 1041 SL 1 GE Advance Scan.source1_holder
+0009 1042 FL 1 GE Advance Scan.source1_activity
+0009 1043 DT 1 GE Advance Scan.source1_meas_dt
+0009 1044 SH 1 GE Advance Scan.source1_radnuclide
+0009 1045 FL 1 GE Advance Scan.source1_half_life
+0009 1046 SL 1 GE Advance Scan.source2_holder
+0009 1047 FL 1 GE Advance Scan.source2_activity
+0009 1048 DT 1 GE Advance Scan.source2_meas_dt
+0009 1049 SH 1 GE Advance Scan.source2_radnuclide
+0009 104a FL 1 GE Advance Scan.source2_half_life
+0009 104b SL 1 GE Advance Scan.source_speed
+0009 104c FL 1 GE Advance Scan.source_location
+0009 104d SL 1 GE Advance Scan.emission_present
+0009 104e SL 1 GE Advance Scan.lower_axial_acc
+0009 104f SL 1 GE Advance Scan.upper_axial_acc
+0009 1050 SL 1 GE Advance Scan.lower_coinc_limit
+0009 1051 SL 1 GE Advance Scan.upper_coinc_limit
+0009 1052 SL 1 GE Advance Scan.coinc_delay_offset
+0009 1053 SL 1 GE Advance Scan.coinc_output_mode
+0009 1054 SL 1 GE Advance Scan.upper_energy_limit
+0009 1055 SL 1 GE Advance Scan.lower_energy_limit
+0009 1056 UI 1 GE Advance Scan.normal_cal_id
+0009 1057 UI 1 GE Advance Scan.normal_2d_cal_id
+0009 1058 UI 1 GE Advance Scan.blank_cal_id
+0009 1059 UI 1 GE Advance Scan.wc_cal_id
+0009 105a SL 1 GE Advance Scan.derived
+0009 105b LO 1 GE Advance Scan.contrast_agent
+0009 105c UI 1 GE Advance Frame.frame_id
+0009 105d UI 1 GE Advance Frame.scan_id
+0009 105e UI 1 GE Advance Frame.exam_id
+0009 105f LO 1 GE Advance Frame.patient_id
+0009 1060 SH 1 GE Advance Frame.compatible_version
+0009 1061 SH 1 GE Advance Frame.software_version
+0009 1062 ST 1 GE Advance Frame.where_is_frame
+0009 1063 SL 1 GE Advance Frame.frame_size
+0009 1064 SL 1 GE Advance Frame.file_exists
+0009 1065 SL 1 GE Advance Frame.patient_entry
+0009 1066 FL 1 GE Advance Frame.table_height
+0009 1067 FL 1 GE Advance Frame.table_z_position
+0009 1068 DT 1 GE Advance Frame.landmark_datetime
+0009 1069 SL 1 GE Advance Frame.slice_count
+0009 106a FL 1 GE Advance Frame.start_location
+0009 106b SL 1 GE Advance Frame.acq_delay
+0009 106c DT 1 GE Advance Frame.acq_start
+0009 106d SL 1 GE Advance Frame.acq_duration
+0009 106e SL 1 GE Advance Frame.acq_bin_dur
+0009 106f SL 1 GE Advance Frame.acq_bin_start
+0009 1070 SL 1 GE Advance Frame.actual_stop_cond
+0009 1071 FD 1 GE Advance Frame.total_prompts
+0009 1072 FD 1 GE Advance Frame.total_delays
+0009 1073 SL 1 GE Advance Frame.frame_valid
+0009 1074 SL 1 GE Advance Frame.validity_info
+0009 1075 SL 1 GE Advance Frame.archived
+0009 1076 SL 1 GE Advance Frame.compression
+0009 1077 SL 1 GE Advance Frame.uncompressed_size
+0009 1078 SL 1 GE Advance Frame.accum_bin_dur
+0009 1079 SH 1 GE Advance ImageSet.compatible_version
+0009 107a SH 1 GE Advance ImageSet.software_version
+0009 107b DT 1 GE Advance ImageSet.is_datetime
+0009 107c SL 1 GE Advance ImageSet.is_source
+0009 107d SL 1 GE Advance ImageSet.is_contents
+0009 107e SL 1 GE Advance ImageSet.is_type
+0009 107f FL 3 GE Advance ImageSet.is_reference
+0009 1080 SL 1 GE Advance ImageSet.multi_patient
+0009 1081 SL 1 GE Advance ImageSet.number_of_normals
+0009 1082 UI 1 GE Advance ImageSet.color_map_id
+0009 1083 SL 1 GE Advance ImageSet.window_level_type
+0009 1084 FL 1 GE Advance ImageSet.rotate
+0009 1085 SL 1 GE Advance ImageSet.flip
+0009 1086 FL 1 GE Advance ImageSet.zoom
+0009 1087 SL 1 GE Advance ImageSet.pan_x
+0009 1088 SL 1 GE Advance ImageSet.pan_y
+0009 1089 FL 1 GE Advance ImageSet.window_level_min
+0009 108a FL 1 GE Advance ImageSet.window_level_max
+0009 108b SL 1 GE Advance ImageSet.recon_method
+0009 108c SL 1 GE Advance ImageSet.attenuation
+0009 108d FL 1 GE Advance ImageSet.atten_coefficient
+0009 108e SL 1 GE Advance ImageSet.bp_filter
+0009 108f FL 1 GE Advance ImageSet.bp_filter_cutoff
+0009 1090 SL 1 GE Advance ImageSet.bp_filter_order
+0009 1091 FL 1 GE Advance ImageSet.bp_center_l
+0009 1092 FL 1 GE Advance ImageSet.bp_center_p
+0009 1093 SL 1 GE Advance ImageSet.atten_smooth
+0009 1094 SL 1 GE Advance ImageSet.atten_smooth_param
+0009 1095 SL 1 GE Advance ImageSet.angle_smooth_param
+0009 1096 UI 1 GE Advance ImageSet.wellcountercal_id
+0009 1097 UI 1 GE Advance ImageSet.trans_scan_id
+0009 1098 UI 1 GE Advance ImageSet.norm_cal_id
+0009 1099 UI 1 GE Advance ImageSet.blnk_cal_id
+0009 109a FL 1 GE Advance ImageSet.cac_edge_threshold
+0009 109b FL 1 GE Advance ImageSet.cac_skull_offset
+0009 109c UI 1 GE Advance ImageSet.emiss_sub_id
+0009 109d SL 1 GE Advance ImageSet.radial_filter_3d
+0009 109e FL 1 GE Advance ImageSet.radial_cutoff_3d
+0009 109f SL 1 GE Advance ImageSet.axial_filter_3d
+0009 10a0 FL 1 GE Advance ImageSet.axial_cutoff_3d
+0009 10a1 FL 1 GE Advance ImageSet.axial_start
+0009 10a2 FL 1 GE Advance ImageSet.axial_spacing
+0009 10a3 SL 1 GE Advance ImageSet.axial_angles_used
+0009 10b2 SL 1 GE Advance ImageSet.ir_num_iterations
+0009 10b3 SL 1 GE Advance ImageSet.ir_num_subsets
+0009 10b4 FL 1 GE Advance ImageSet.ir_recon_fov
+0009 10b5 SL 1 GE Advance ImageSet.ir_corr_model
+0009 10b6 SL 1 GE Advance ImageSet.ir_loop_filter
+0009 10b7 FL 1 GE Advance ImageSet.ir_pre_filt_parm
+0009 10b8 SL 1 GE Advance ImageSet.ir_loop_filt_parm
+0009 10b9 FL 1 GE Advance ImageSet.response_filt_parm
+0009 10ba SL 1 GE Advance ImageSet.post_filter
+0009 10bb FL 1 GE Advance ImageSet.post_filt_parm
+0009 10bc SL 1 GE Advance ImageSet.ir_regularize
+0009 10bd FL 1 GE Advance ImageSet.regularize_parm
+0009 10be SL 1 GE Advance ImageSet.ac_bp_filter
+0009 10bf FL 1 GE Advance ImageSet.ac_bp_filt_cut_off
+0009 10c0 SL 1 GE Advance ImageSet.ac_bp_filt_order
+0009 10c1 SL 1 GE Advance ImageSet.ac_img_smooth
+0009 10c2 FL 1 GE Advance ImageSet.ac_img_smooth_parm
+0009 10c3 SL 1 GE Advance ImageSet.scatter_method
+0009 10c4 SL 1 GE Advance ImageSet.scatter_num_iter
+0009 10c5 FL 1 GE Advance ImageSet.scatter_parm
+0009 10a4 SH 1 GE Advance Image.compatible_version
+0009 10a5 SH 1 GE Advance Image.software_version
+0009 10a6 SL 1 GE Advance Image.slice_number
+0009 10a7 FL 1 GE Advance Image.total_counts
+0009 10a8 OB 1 GE Advance Image.other_atts
+0009 10a9 SL 1 GE Advance Image.other_atts_size
+0009 10aa SL 1 GE Advance Image.archived
+0009 10ab FL 1 GE Advance Image.bp_center_x
+0009 10ac FL 1 GE Advance Image.bp_center_y
+0009 10ad UI 1 GE Advance Image.trans_frame_id
+0009 10ae UI 1 GE Advance Image.tpluse_frame_id
+0009 10c6 FL 1 GE Advance Image.seg_qc_parm
+0009 10c7 SL 1 GE Advance Image.overlap
+0009 10c8 UI 1 GE Advance Image.ovlp_frm_id
+0009 10c9 UI 1 GE Advance Image.ovlp_trans_frm_id
+0009 10ca UI 1 GE Advance Image.ovlp_tpulse_frm_id
+0011 0010 SH 1 Private Creator Data Element
+0011 1001 SQ 1 GE Advance ROI Sequence
+0011 1002 UI 1 > GE Advance ROI.roi_id
+0011 1003 UI 1 > GE Advance ROI.image_id
+0011 1004 SH 1 > GE Advance ROI.compatible_version
+0011 1005 SH 1 > GE Advance ROI.software_version
+0011 1006 LO 1 > GE Advance ROI.roi_name
+0011 1007 DT 1 > GE Advance ROI.roi_datetime
+0011 1008 SL 1 > GE Advance ROI.roi_type
+0011 1009 FL 1 > GE Advance ROI.center_x
+0011 100a FL 1 > GE Advance ROI.center_y
+0011 100b FL 1 > GE Advance ROI.width
+0011 100c FL 1 > GE Advance ROI.height
+0011 100d FL 1 > GE Advance ROI.angle
+0011 100e SL 1 > GE Advance ROI.number_of_points
+0011 100f OB 1 > GE Advance ROI.roi_data
+0011 1010 SL 1 > GE Advance ROI.roi_size
+0011 1011 LO 1 > GE Advance ROI.color
+0011 1012 SL 1 > GE Advance ROI.line_type
+0011 1013 SL 1 > GE Advance ROI.line_width
+0011 1014 SL 1 > GE Advance ROI.roi_number
+0011 1015 SL 1 > GE Advance ROI.convex
+0011 1016 SL 1 > GE Advance ROI.atten_corr_flag
+0013 0010 SH 1 Private Creator Data Element
+0013 1001 SQ 1 GE Advance Annotation Sequence
+0013 1002 UI 1 > GE Advance Annotation.annotation_id
+0013 1003 UI 1 > GE Advance Annotation.image_id
+0013 1004 SH 1 > GE Advance Annotation.compatible_version
+0013 1005 SH 1 > GE Advance Annotation.software_version
+0013 1006 SL 1 > GE Advance Annotation.type
+0013 1007 LO 1 > GE Advance Annotation.font_name
+0013 1008 SH 1 > GE Advance Annotation.font_size
+0013 1009 LO 1 > GE Advance Annotation.foreground_color
+0013 100a LO 1 > GE Advance Annotation.background_color
+0013 100b SL 1 > GE Advance Annotation.coordinate_system
+0013 100c FL 1 > GE Advance Annotation.start_x
+0013 100d FL 1 > GE Advance Annotation.start_y
+0013 100e FL 1 > GE Advance Annotation.end_x
+0013 100f FL 1 > GE Advance Annotation.end_y
+0013 1010 SL 1 > GE Advance Annotation.start_symbol
+0013 1011 SL 1 > GE Advance Annotation.end_symbol
+0013 1012 OB 1 > GE Advance Annotation.annotation_data
+0013 1013 SL 1 > GE Advance Annotation.annotation_size
+0013 1014 LO 1 > GE Advance Annotation.label_id
+5001 0010 SH 1 Private Creator Data Element
+5001 1001 UI 1 GE Advance Curve.curve_id
+5001 1002 SH 1 GE Advance Curve.compatible_version
+5001 1003 SH 1 GE Advance Curve.software_version
+5001 1004 SL 1 GE Advance Curve.statistics_type
+5001 1005 LT 1 GE Advance Curve.how_derived
+5001 1006 SL 1 GE Advance Curve.how_derived_size
+5001 1007 SL 1 GE Advance Curve.multi_patient
+5001 1008 SL 1 GE Advance Curve.deadtime
+5003 0010 SH 1 Private Creator Data Element
+5003 1001 SQ 1 GE Advance Graph Sequence
+5003 1002 UI 1 > GE Advance Graph.graph_id
+5003 1003 SH 1 > GE Advance Graph.compatible_version
+5003 1004 SH 1 > GE Advance Graph.software_version
+5003 1005 LO 1 > GE Advance Graph.title
+5003 1006 DT 1 > GE Advance Graph.graph_datetime
+5003 1007 ST 1 > GE Advance Graph.graph_description
+5003 1008 LO 1 > GE Advance Graph.title_font_name
+5003 1009 SH 1 > GE Advance Graph.title_font_size
+5003 100a LO 1 > GE Advance Graph.footer
+5003 100b SH 1 > GE Advance Graph.footer_font_size
+5003 100c LO 1 > GE Advance Graph.foreground_color
+5003 100d LO 1 > GE Advance Graph.background_color
+5003 100e SL 1 > GE Advance Graph.graph_border
+5003 100f SL 1 > GE Advance Graph.graph_width
+5003 1010 SL 1 > GE Advance Graph.graph_height
+5003 1011 SL 1 > GE Advance Graph.grid
+5003 1012 LO 1 > GE Advance Graph.label_font_name
+5003 1013 SH 1 > GE Advance Graph.label_font_size
+5003 1014 LO 1 > GE Advance Graph.axes_color
+5003 1015 LO 1 > GE Advance Graph.x_axis_label
+5003 1016 SL 1 > GE Advance Graph.x_axis_units
+5003 1017 FL 1 > GE Advance Graph.x_major_tics
+5003 1018 FL 1 > GE Advance Graph.x_axis_min
+5003 1019 FL 1 > GE Advance Graph.x_axis_max
+5003 101a LO 1 > GE Advance Graph.y_axis_label
+5003 101b SL 1 > GE Advance Graph.y_axis_units
+5003 101c FL 1 > GE Advance Graph.y_major_tics
+5003 101d FL 1 > GE Advance Graph.y_axis_min
+5003 101e FL 1 > GE Advance Graph.y_axis_max
+5003 101f LO 1 > GE Advance Graph.legend_font_name
+5003 1020 SH 1 > GE Advance Graph.legend_font_size
+5003 1021 SL 1 > GE Advance Graph.legend_location_x
+5003 1022 SL 1 > GE Advance Graph.legend_location_y
+5003 1023 SL 1 > GE Advance Graph.legend_width
+5003 1024 SL 1 > GE Advance Graph.legend_height
+5003 1025 SL 1 > GE Advance Graph.legend_border
+5003 1026 SL 1 > GE Advance Graph.multi_patient
+5005 0010 SH 1 Private Creator Data Element
+5005 1001 SQ 1 GE Advance CurvePresentation Sequence
+5005 1002 UI 1 > GE Advance CurvePresentation.curvepresent_id
+5005 1003 UI 1 > GE Advance CurvePresentation.graph_id
+5005 1004 UI 1 > GE Advance CurvePresentation.curve_id
+5005 1005 SH 1 > GE Advance CurvePresentation.compatible_version
+5005 1006 SH 1 > GE Advance CurvePresentation.software_version
+5005 1007 LO 1 > GE Advance CurvePresentation.curve_label
+5005 1008 LO 1 > GE Advance CurvePresentation.color
+5005 1009 SL 1 > GE Advance CurvePresentation.line_type
+5005 100a SL 1 > GE Advance CurvePresentation.line_width
+5005 100b SL 1 > GE Advance CurvePresentation.point_symbol
+5005 100c SL 1 > GE Advance CurvePresentation.point_symbol_dim
+5005 100d LO 1 > GE Advance CurvePresentation.point_color
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Advantx.dic b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Advantx.dic
new file mode 100644
index 0000000000000000000000000000000000000000..ac7dc921d43ce50915d6577e8148127b93fac529
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Advantx.dic
@@ -0,0 +1,35 @@
+0011 00xx LO 1 Private Creator PATIENT_01
+0011 xx01 LT 1 Patient DOB
+0015 00xx LO 1 Private Creator EXAM_01
+0015 xx01 DS 1 Stenos_calibr_ratio
+0015 xx02 DS 1 Stenos_magnification
+0015 xx03 DS 1 Cardiac_calibr_ratio
+0019 00xx LO 1 Private Creator SERIE_01
+0019 xx01 DS 1 Angle_value_1
+0019 xx02 DS 1 Angle_value_2
+0019 xx03 DS 1 Angle_value_3
+0019 xx04 CS 1 Angle_label_1
+0019 xx05 CS 1 Angle_label_2
+0019 xx06 CS 1 Angle_label_3
+0019 xx07 ST 1 Adx_procedure_name
+0019 xx08 ST 1 Adx_exam_name
+0019 xx09 SH 1 Adx_patient_size
+0019 000A IS 1 Acq_record view
+0019 xx10 DS 1 Adx_injector_delay
+0019 xx11 CS 1 Adx_auto_inject
+0019 xx14 IS 1 Adx_acq_mod
+0019 xx15 CS 1 Adx_camera_rotation_enable
+0019 xx16 CS 1 Adx_reverse_sweep
+0019 xx17 IS 1 Cur_spatial_filter_strength
+0019 xx18 IS 1 Zoom_factor
+0019 xx19 IS 1 X_zoom
+0019 xx1A IS 1 Y_zoom
+0019 xx1B DS 1 Adx_focus
+0019 xx1C CS 1 Adx_dose
+0019 xx1D IS 1 Side_mark
+0019 xx1E IS 1 Percentage_landscape
+0019 xx1F DS 1 Adx_exposure_duration
+70nn 00xx LO 1 Private Creator ANNOT_01
+70nn xx04 ST 1 Text_annotation
+70nn xx05 IS 2 Box
+70nn xx07 IS 2 Arrow end
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-CR.dic b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-CR.dic
new file mode 100644
index 0000000000000000000000000000000000000000..f4b91a6027b2af3eaa16de417e2be4c7e38425ec
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-CR.dic
@@ -0,0 +1,33 @@
+0023 0010 LO 1 Private Creator
+0023 1000 LO 1 CR Exposure Menu Code
+0023 1010 LO 1 CR Exposure Menu String
+0023 1020 LO 1 CR EDR Mode
+0023 1030 LO 1 CR Latitude
+0023 1040 LO 1 CR Group Number
+0023 1050 LO 1 CR Image Serial Number
+0023 1060 LO 1 CR Bar Code Number
+0023 1070 LO 1 CR Film Output Exposure
+0023 1080 LO 1 CR Film Format
+0023 1090 LO 1 CR S-Shift String
+0023 2000 SS 1 CR S-Shift
+0023 2010 LO 1 CR C-Shift
+0023 2020 LO 1 CR GT
+0023 2030 LO 1 CR GA
+0023 2040 LO 1 CR GC
+0023 2050 LO 1 CR GS
+0023 2060 LO 1 CR RT
+0023 2070 LO 1 CR RE
+0023 2080 US 1 CR RN
+0023 2090 LO 1 CR DRT
+0023 3000 LO 1 CR DRE
+0023 3010 US 1 CR DRN
+0023 3020 LO 1 CR ORE
+0023 3030 SS 1 CR ORN
+0023 3040 SS 1 CR ORD
+0023 3050 LO 1 CR Cassette Size
+0023 3060 LO 1 CR Machine ID
+0023 3070 LO 1 CR Machine Type
+0023 3080 LO 1 CR Technician Code
+0023 3090 LO 1 CR Energy Subtraction value
+0023 30f0 LO 1 CR Distribution Code
+0023 30ff US 1 CR Shutters Applied
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-DLX.dic b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-DLX.dic
new file mode 100644
index 0000000000000000000000000000000000000000..64e832596a77a3d09d93e6429096def564c951c8
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-DLX.dic
@@ -0,0 +1,29 @@
+0011 1001 LT 1 Patient DOB
+0015 1001 DS 1 Stenosis Calibration Ratio
+0015 1002 DS 1 Stenosis Magnification
+0015 1003 DS 1 Cardiac Calibration Ratio
+
+0019 1001 DS 1 Angle Value L Arm
+0019 1002 DS 1 Angle Value P Arm
+0019 1003 DS 1 Angle Value C Arm
+0019 1004 CS 1 Angle Label L Arm
+0019 1005 CS 1 Angle Label P Arm
+0019 1006 CS 1 Angle Label C Arm
+0019 1007 ST 1 Adx Procedure Name
+0019 1008 ST 1 Adx Exam Name
+0019 1009 SH 1 Adx Patient Size
+0019 100a IS 1 Acquisition Record View
+0019 1010 DS 1 Adx Injector Delay
+0019 1011 CS 1 Adx Auto Inject
+0019 1014 IS 1 Adx Acquisition Mode
+0019 1015 CS 1 Adx Camera Rotation Enabled
+0019 1016 CS 1 Adx Reverse Sweep
+0019 1017 IS 1 Cur Spatial Filter Strength
+0019 1018 IS 1 Zoom Factor
+0019 1019 IS 1 X Zoom
+0019 101a IS 1 Y Zoom
+0019 101b DS 1 Adx Focus
+0019 101c CS 1 Adx Dose
+0019 101d IS 1 Side Mark
+0019 101e IS 1 Percentage Landscape
+0019 101f DS 1 Adx Exposure Duration
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Genie.dic b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Genie.dic
new file mode 100644
index 0000000000000000000000000000000000000000..303948d6de2b92dbe324c25761df59642812afaa
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Genie.dic
@@ -0,0 +1,87 @@
+0009 0010 LO 1 Private Creator Identification 
+0009 xx11 SL 1 Study Flags 
+0009 xx12 SL 1 Study Type 
+0009 xx21 SL 1 Series Flags 
+0009 xx22 SH 1 User Orientation 
+0009 xx23 SL 1 Initiation Type 
+0009 xx24 SL 1 Initiation Delay 
+0009 xx25 SL 1 Initiation Count Rate 
+0009 xx26 SL 1 Number Energy Sets 
+0009 xx27 SL 1 Number Detectors 
+0009 xx2c LO 1 Series Comments
+0009 xx2d SL 1 Track Beat Average 
+0009 xx2e FD 1 Distance Prescribed 
+0009 xx35 SL 1 Gantry Locus Type 
+0009 xx37 SL 1 Starting Heart Rate 
+0009 xx38 SL 1 RR Window Width 
+0009 xx39 SL 1 RR Window Offset 
+0009 xx3a SL 1 Percent Cycle Imaged 
+0009 xx40 PN 1 Patient Object Name
+0009 xx41 SL 1 Patient Flags
+0009 xx42 DA 1 Patient Creation Date
+0009 xx43 TM 1 Patient Creation Time
+0011 0010 LO 1 Private Creator Identification 
+0011 xx0a SL 1 Series Type  
+0011 xx0b SL 1 Effective Series Duration 
+0011 xx0c SL 1 Num Beats 
+0011 xx0d LO 1 Radio Nuclide Name 
+0011 xx12 LO 1 Dataset Name 
+0011 xx13 SL 1 Dataset Type 
+0011 xx15 SL 1 Detector Number 
+0011 xx16 SL 1 Energy Number 
+0011 xx17 SL 1 RR Interval Window Number 
+0011 xx18 SL 1 MG Bin Number 
+0011 xx19 FD 1 Radius Of Rotation  
+0011 xx1a SL 1 Detector Count Zone 
+0011 xx1b SL 1 Num Energy Windows 
+0011 xx1c SL 4 Energy Offset 
+0011 xx1d SL 1 Energy Range 
+0011 xx1f SL 1 Image Orientation 
+0011 xx23 SL 1 Use FOV Mask 
+0011 xx24 SL 1 FOV Mask Y Cutoff Angle 
+0011 xx25 SL 1 FOV Mask Cutoff Angle 
+0011 xx26 SL 1 Table Orientation 
+0011 xx27 SL 2 ROI Top Left 
+0011 xx28 SL 2 ROI Bottom Right 
+0011 xx33 LO 1 Energy Correct Name 
+0011 xx34 LO 1 Spatial Correct Name 
+0011 xx35 LO 1 Tuning Calib Name 
+0011 xx36 LO 1 Uniformity Correct Name 
+0011 xx37 LT 1 Acquisition Specific Correction Name 
+0011 xx38 SL 1 Byte Order 
+0011 xx3a SL 1 Picture Format 
+0011 xx3b FD 1 Pixel Scale 
+0011 xx3c FD 1 Pixel Offset 
+0011 xx3e SL 1 FOV Shape 
+0011 xx3f SL 1 Dataset Flags 
+0011 xx44 FD 1 Threshold Center 
+0011 xx45 FD 1 Threshold Width 
+0011 xx46 SL 1 Interpolation Type 
+0011 xx55 FD 1 Period 
+0011 xx56 FD 1 Elapsed Time 
+0013 0010 LO 1 Private Creator Identification 
+0013 xx10 FD 2 Digital FOV 
+0013 xx11 SL 1 Source Translator
+0013 xx16 SL 1 AutoTrack Peak 
+0013 xx17 SL 1 AutoTrack Width 
+0013 xx18 FD 1 Transmission Scan Time 
+0013 xx19 FD 1 Transmission Mask Width 
+0013 xx1a FD 1 Copper Attenuator Thickness 
+0013 xx1e FD 1-n Tomo View Offset 
+0013 xx26 LT 1 Study Comments
+0033 xx08 CS 1 GENIE Data Object Type
+0033 xx10 SL 1 Modified
+0033 xx11 LO 1 Name
+0033 xx16 LO 1 ProtocolDataUID
+0033 xx17 SH 1 Date
+0033 xx18 SH 1 Time
+0033 xx19 UL 1 ProtocoldataFlags
+0033 xx1A UL 1 ProtocolName
+0033 xx1B LO 1 RelevantDataUID
+0033 xx1C LO 1 BulkData
+0033 xx1D SL 1-n IntData
+0033 xx1E FD 1-n DoubleData
+0033 xx1F LT 1-n StringData
+0033 xx20 LT 1-n BulkDataFormat
+0033 xx23 LT 1-n StringDataFormat
+0033 xx24 LT 1 Description
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-HiSpeed.dic b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-HiSpeed.dic
new file mode 100644
index 0000000000000000000000000000000000000000..68999f670562a6469b75100abb7d28a2c2375cce
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-HiSpeed.dic
@@ -0,0 +1,34 @@
+0009 1031 SH 1 Mobile Location Code 
+0019 1002 SL 1 Detector Channel 
+0019 1023 DS 1 Table Speed 
+0019 1024 DS 1 mid scan time 
+0019 1026 SL 1 Tube Azimuth 
+0019 1027 DS 1 Gantry Velocity 
+0019 1039 SS 1 SFOV Type 
+0019 1042 SS 1 Segment number 
+0019 1043 SS 1 Total segments required 
+0043 1012 SS 3 X-Ray Chain 
+0043 101e DS 1 Delta start time 
+0043 1035 US 1 Infant indicator 
+0043 1036 CS 1 language 
+0043 1037 CS 1 Gantry type 
+0043 1038 SH 1 Raw data ID 
+0043 1039 IS 1 Reconstruction Matrix 
+0043 1040 CS 1-n Image Filter 
+0043 1041 US 1 Prospective Addition Indicator 
+0043 1043 US 1 Motion Correction Indicator 
+0043 1044 US 1 Helical Correction Indicator 
+0043 1045 US 1 Cine Correction Indicator
+0043 1046 US 1 IBO Correction Indicator 
+0043 1047 US 1 BBH Correction Indicator 
+0043 1048 US 1 Advanced Noise Reduction Indicator 
+0043 1049 US 1 Scatter Correction Indicator 
+0043 104a DS 3 Recon Center Coordinates 
+0043 1050 US 1 Cross-Talk Correction Indicator 
+0043 1051 US 1 Q-Cal Correction Indicator 
+0043 1052 US 1 Afterglow Correction Indicator 
+0043 1053 US 1 Local Decon Correction Indicator 
+0043 1054 DS 1 Scan Start Location 
+0043 1055 DS 1 Scan End Location 
+0043 1056 IS 1 Detector Row 
+0043 1057 CS 1 Tube Focus 
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Infinia.dic b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Infinia.dic
new file mode 100644
index 0000000000000000000000000000000000000000..654357775edf8666d4d352e78283434d06b8c831
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS-Infinia.dic
@@ -0,0 +1,87 @@
+0009 xx10 LO 1 Study Name
+0009 xx11 SL 1 Study Flags
+0009 xx12 SL 1 Study Type
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0009 xx40 PN 1 Patient Object Name
+0009 xx41 SL 1 Patient Flags
+0009 xx42 DA 1 Patient Creation Date
+0009 xx43 TM 1 Patient Creation Time
+
+
+
+
+0011 xx0d LO 1 Radio Nuclide Name
+0011 xx12 LO 1 Dataset Name
+
+0011 xx15 SL 1 Detector Number
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0013 xx11 SL 1 Source Translator
+
+
+
+
+
+
+0013 xx26 LT 1 Study Comments
+0033 xx08 CS 1 GENIE Data Object Type
+0033 xx10 SL 1 Modified
+0033 xx11 LO 1 Name
+0033 xx16 LO 1 ProtocolDataUID
+0033 xx17 SH 1 Date
+0033 xx18 SH 1 Time
+0033 xx19 UL 1 ProtocoldataFlags
+0033 xx1A UL 1 ProtocolName
+0033 xx1B LO 1 RelevantDataUID
+0033 xx1C LO 1 BulkData
+0033 xx1D SL 1-n IntData
+0033 xx1E FD 1-n DoubleData
+0033 xx1F LT 1-n StringData
+0033 xx20 LT 1-n BulkDataFormat
+0033 xx23 LT 1-n StringDataFormat
+0033 xx24 LT 1 Description
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/GEMS.dic b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS.dic
new file mode 100644
index 0000000000000000000000000000000000000000..bdcc7b6c20cd584725505116fe58edf2e72d0743
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/GEMS.dic
@@ -0,0 +1,394 @@
+0009 0000 UL 1 Group Length
+0009 0010 LO 1 Private Creator Identification (GEMS_IDEN_01) 
+0009 1001 LO 1 Full fidelity
+0009 1002 SH 1 Suite id
+0009 1004 SH 1 Product id
+0009 1027 SL 1 Image actual date
+0009 1030 SH 1 Service id
+0009 1031 SH 1 Mobile location number
+0009 10e3 UI 1 Equipment UID
+0009 10e6 SH 1 Genesis Version - now
+0009 10e7 UL 1 Exam Record checksum
+0009 10e9 SL 1 Actual series data time stamp
+
+0011 0000 UL 1 Group Length
+0011 0010 LO 1 Private Creator Identification (GEMS_PATI_01) 
+0011 1010 SS 1 Patient Status
+
+0019 0000 UL 1 Group Length
+0019 0010 LO 1 Private Creator Identification (GEMS_ACQU_01) 
+0019 1002 SL 1 Number of cells I in Detector
+0019 1003 DS 1 Cell number at Theta
+0019 1004 DS 1 Cell spacing
+0019 100f DS 1 Horiz. Frame of ref.
+0019 1011 SS 1 Series contrast
+0019 1012 SS 1 Last pseq
+0019 1013 SS 1 Start number for baseline
+0019 1014 SS 1 End number for baseline
+0019 1015 SS 1 Start number for enhanced scans
+0019 1016 SS 1 End number for enhanced scans
+0019 1017 SS 1 Series plane
+0019 1018 LO 1 First scan ras
+0019 1019 DS 1 First scan location
+0019 101a LO 1 Last scan ras
+0019 101b DS 1 Last scan loc
+0019 101e DS 1 Display field of view
+0019 1023 DS 1 Table speed
+0019 1024 DS 1 Mid scan time
+0019 1025 SS 1 Mid scan flag
+0019 1026 SL 1 Degrees of azimuth
+0019 1027 DS 1 Gantry period
+0019 102a DS 1 x-ray On position
+0019 102b DS 1 x-ray Off position
+0019 102c SL 1 Number of triggers
+0019 102e DS 1 Angle of first view
+0019 102f DS 1 Trigger frequency
+0019 1039 SS 1 Scan FOV type
+0019 1040 SS 1 Stat recon flag
+0019 1041 SS 1 Compute type
+0019 1042 SS 1 Segment number
+0019 1043 SS 1 Total segments requested
+0019 1044 DS 1 Interscan delay
+0019 1047 SS 1 View compression factor
+0019 104a SS 1 Total no. of ref channels
+0019 104b SL 1 Data size for scan data
+0019 1052 SS 1 Recon post proc. Flag
+0019 1057 SS 1 CT water number
+0019 1058 SS 1 CT bone number
+0019 105a FL 1 Acquisition Duration
+0019 105e SL 1 Number of channels (1...512)
+0019 105f SL 1 Increment between channels
+0019 1060 SL 1 Starting view
+0019 1061 SL 1 Number of views
+0019 1062 SL 1 Increment between views
+0019 106a SS 1 Dependent on #views processed
+0019 106b SS 1 Field of view in detector cells
+0019 1070 SS 1 Value of back projection button
+0019 1071 SS 1 Set if fatq estimates were used
+0019 1072 DS 1 Z chan avg over views
+0019 1073 DS 1 Avg of left ref chans over views
+0019 1074 DS 1 Max left chan over views
+0019 1075 DS 1 Avg of right ref chans over views
+0019 1076 DS 1 Max right chan over views
+0019 107d DS 1 Second echo
+0019 107e SS 1 Number of echoes
+0019 107f DS 1 Table delta
+0019 1081 SS 1 Contiguous
+0019 1084 DS 1 Peak SAR
+0019 1085 SS 1 Monitor SAR
+0019 1087 DS 1 Cardiac repetition time
+0019 1088 SS 1 Images per cardiac cycle
+0019 108a SS 1 Actual receive gain analog
+0019 108b SS 1 Actual receive gain digital
+0019 108d DS 1 Delay after trigger
+0019 108f SS 1 Swappf
+0019 1090 SS 1 Pause Interval
+0019 1091 DS 1 Pulse Time
+0019 1092 SL 1 Slice offset on freq axis
+0019 1093 DS 1 Center Frequency
+0019 1094 SS 1 Transmit Gain
+0019 1095 SS 1 Analog receiver gain
+0019 1096 SS 1 Digital receiver gain
+0019 1097 SL 1 Bitmap defining CVs
+0019 1098 SS 1 Center freq. Method
+0019 109b SS 1 Pulse seq. Mode
+0019 109c LO 1 Pulse seq. Name
+0019 109d DT 1 Pulse seq. Date
+0019 109e LO 1 Internal pulse seq. Name
+0019 109f SS 1 Transmitting coil
+0019 10a0 SS 1 Surface Coil Type
+0019 10a1 SS 1 Extremity Coil flag
+0019 10a2 SL 1 Raw data run number
+0019 10a3 UL 1 Calibrated Field strength
+0019 10a4 SS 1 SAT fat/water/bone
+0019 10a5 DS 1 Receive bandwidth
+0019 10a7 DS 1 User data
+0019 10a8 DS 1 User data
+0019 10a9 DS 1 User data
+0019 10aa DS 1 User data
+0019 10ab DS 1 User data
+0019 10ac DS 1 User data
+0019 10ad DS 1 User data
+0019 10ae DS 1 User data
+0019 10af DS 1 User data
+0019 10b0 DS 1 User data
+0019 10b1 DS 1 User data
+0019 10b2 DS 1 User data
+0019 10b3 DS 1 User data
+0019 10b4 DS 1 User data
+0019 10b5 DS 1 User data
+0019 10b6 DS 1 User data
+0019 10b7 DS 1 User data
+0019 10b8 DS 1 User data
+0019 10b9 DS 1 User data
+0019 10ba DS 1 User data
+0019 10bb DS 1 User data
+0019 10bc DS 1 User data
+0019 10bd DS 1 User data
+0019 10be DS 1 Projection angle
+0019 10c0 SS 1 Saturation planes
+0019 10c1 SS 1 Surface coil intensity
+0019 10c2 SS 1 SAT location R
+0019 10c3 SS 1 SAT location L
+0019 10c4 SS 1 SAT location A
+0019 10c5 SS 1 SAT location P
+0019 10c6 SS 1 SAT location H
+0019 10c7 SS 1 SAT location F
+0019 10c8 SS 1 SAT thickness R/L
+0019 10c9 SS 1 SAT thickness A/P
+0019 10ca SS 1 SAT thickness H/F
+0019 10cb SS 1 Prescribed flow axis
+0019 10cc SS 1 Velocity encoding
+0019 10cd SS 1 Thickness disclaimer
+0019 10ce SS 1 Prescan type
+0019 10cf SS 1 Prescan status
+0019 10d0 SH 1 Raw data type
+0019 10d2 SS 1 Projection Algorithm
+0019 10d3 SH 1 Projection algorithm
+0019 10d5 SS 1 Fractional echo
+0019 10d6 SS 1 Prep pulse
+0019 10d7 SS 1 Cardiac phases
+0019 10d8 SS 1 Variable echoflag
+0019 10d9 DS 1 Concatenated SAT
+0019 10da SS 1 Reference channel used
+0019 10db DS 1 Back projector coefficient
+0019 10dc SS 1 Primary speed correction used
+0019 10dd SS 1 Overrange correction used
+0019 10de DS 1 Dynamic Z alpha value
+0019 10df DS 1 User data
+0019 10e0 DS 1 User data
+0019 10e2 DS 1 Velocity Encode Scale
+0019 10f2 SS 1 Fast phases
+0019 10f9 DS 1 Transmission gain
+
+0021 0000 UL 1 Group Length
+0021 0010 LO 1 Private Creator Identification (GEMS_RELA_01) 
+0021 1003 SS 1 Series from which Prescribed
+0021 1005 SH 1 Genesis Version - now
+0021 1007 UL 1 Series Record checksum
+0021 1018 SH 1 Genesis version - Now
+0021 1019 UL 1 Acq recon record checksum
+0021 1019 UL 1 Acqrecon record checksum
+0021 1020 DS 1 Table start location
+0021 1035 SS 1 Series from which prescribed
+0021 1036 SS 1 Image from which prescribed
+0021 1037 SS 1 Screen Format
+0021 104a LO 1 Anatomical reference for scout
+0021 104f SS 1 Locations in acquisition
+0021 1050 SS 1 Graphically prescribed
+0021 1051 DS 1 Rotation from source x rot
+0021 1052 DS 1 Rotation from source y rot
+0021 1053 DS 1 Rotation from source z rot
+0021 1054 SH 3 Image position
+0021 1055 SH 6 Image orientation
+0021 1056 SL 1 Integer slop
+0021 1057 SL 1 Integer slop
+0021 1058 SL 1 Integer slop
+0021 1059 SL 1 Integer slop
+0021 105a SL 1 Integer slop
+0021 105b DS 1 Float slop
+0021 105c DS 1 Float slop
+0021 105d DS 1 Float slop
+0021 105e DS 1 Float slop
+0021 105f DS 1 Float slop
+0021 1081 DS 1 Auto window/level alpha
+0021 1082 DS 1 Auto window/level beta
+0021 1083 DS 1 Auto window/level window
+0021 1084 DS 1 To window/level level
+0021 1090 SS 1 Tube focal spot position
+0021 1091 SS 1 Biopsy position
+0021 1092 FL 1 Biopsy T location
+0021 1093 FL 1 Biopsy ref location
+
+0023 0000 UL 1 Group Length
+0023 0010 LO 1 Private Creator Identification (GEMS_STDY_01) 
+0023 1001 SL 1 Number of series in Study
+0023 1002 SL 1 Number of unarchived Series
+0023 1010 SS 1 Reference image field
+0023 1050 SS 1 Summary image
+0023 1070 FD 1 Start time(secs) in first axial
+0023 1074 SL 1 No. of updates to header
+0023 107d SS 1 Indicates if the study has complete info (DICOM/genesis)
+
+0025 0000 UL 1 Group Length
+0025 0010 LO 1 Private Creator Identification (GEMS_SERS_01) 
+0025 1006 SS 1 Last pulse sequence used
+0025 1007 SL 1 Images in Series
+0025 1010 SL 1 Landmark Counter
+0025 1011 SS 1 Number of Acquisitions
+0025 1014 SL 1 Indicates no. of updates to header
+0025 1017 SL 1 Series Complete Flag
+0025 1018 SL 1 Number of images archived
+0025 1019 SL 1 Last image number used
+0025 101a SH 1 Primary Receiver Suite and Host
+
+0027 0000 UL 1 Group Length
+0027 0010 LO 1 Private Creator Identification (GEMS_IMAG_01) 
+0027 1006 SL 1 Image archive flag
+0027 1010 SS 1 Scout Type
+0027 101c SL 1 Vma mamp
+0027 101d SS 1 Vma phase
+0027 101e SL 1 Vma mod
+0027 101f SL 1 Vma clip
+0027 1020 SS 1 Smart scan ON/OFF flag
+0027 1030 SH 1 Foreign Image Revision
+0027 1031 SS 1 Imaging Mode
+0027 1032 SS 1 Pulse Sequence
+0027 1033 SL 1 Imaging Options
+0027 1035 SS 1 Plane Type
+0027 1036 SL 1 Oblique Plane
+0027 1040 SH 1 RAS letter of image location
+0027 1041 FL 1 Image location
+0027 1042 FL 1 Center R coord of plane image
+0027 1043 FL 1 Center A coord of plane image
+0027 1044 FL 1 Center S coord of plane image
+0027 1045 FL 1 Normal R coord
+0027 1046 FL 1 Normal A coord
+0027 1047 FL 1 Normal S coord
+0027 1048 FL 1 R Coord of Top Right Corner
+0027 1049 FL 1 A Coord of Top Right Corner
+0027 104a FL 1 S Coord of Top Right Corner
+0027 104b FL 1 R Coord of Bottom Right Corner
+0027 104c FL 1 A Coord of Bottom Right Corner
+0027 104d FL 1 S Coord of Bottom Right Corner
+0027 1050 FL 1 Table start location
+0027 1051 FL 1 Table end location
+0027 1052 SH 1 RAS letter for side of image
+0027 1053 SH 1 RAS letter for anterior/posterior
+0027 1054 SH 1 RAS letter for scout start loc
+0027 1055 SH 1 RAS letter for scout end loc
+0027 1060 FL 1 Image dimension - X
+0027 1061 FL 1 Image dimension - Y
+0027 1062 FL 1 Number of Excitations
+
+0029 0000 UL 1 Group Length
+0029 0010 LO 1 Private Creator Identification (GEMS_IMPS_01) 
+0029 1004 SL 1 Lower range of Pixels1
+0029 1005 DS 1 Lower range of Pixels1
+0029 1006 DS 1 Lower range of Pixels1
+0029 1007 SL 1 Lower range of Pixels1
+0029 1008 SH 1 Lower range of Pixels1
+0029 1009 SH 1 Lower range of Pixels1
+0029 100a SS 1 Lower range of Pixels1
+0029 1015 SL 1 Lower range of Pixels1
+0029 1016 SL 1 Lower range of Pixels1
+0029 1017 SL 1 Lower range of Pixels2
+0029 1018 SL 1 Upper range of Pixels2
+0029 101a SL 1 Len of tot hdr in bytes
+0029 1026 SS 1 Version of the hdr struct
+0029 1034 SL 1 Advantage comp. Overflow
+0029 1035 SL 1 Advantage comp. Underflow
+
+0043 0000 UL 1 Group Length
+0043 0010 LO 1 Private Creator Identification (GEMS_PARM_01) 
+0043 1001 SS 1 Bitmap of prescan options
+0043 1002 SS 1 Gradient offset in X
+0043 1003 SS 1 Gradient offset in Y
+0043 1004 SS 1 Gradient offset in Z
+0043 1005 SS 1 Img is original or unoriginal
+0043 1006 SS 1 Number of EPI shots
+0043 1007 SS 1 Views per segment
+0043 1008 SS 1 Respiratory rate, bpm
+0043 1009 SS 1 Respiratory trigger point
+0043 100a SS 1 Type of receiver used
+0043 100b DS 1 Peak rate of change of gradient field
+0043 100c DS 1 Limits in units of percent
+0043 100d DS 1 PSD estimated limit
+0043 100e DS 1 PSD estimated limit in tesla per second
+0043 100f DS 1 Saravghead
+0043 1010 US 1 Window value
+0043 1011 US 1 Total input views
+0043 1012 SS 3 X-ray chain
+0043 1013 SS 5 Decon kernel parameters
+0043 1014 SS 3 Calibration parameters
+0043 1015 SS 3 Total output views
+0043 1016 SS 5 Number of overranges
+0043 1017 DS 1 IBH image scale factors
+0043 1018 DS 3 BBH coefficients
+0043 1019 SS 1 Number of BBH chains to blend
+0043 101a SL 1 Starting channel number
+0043 101b SS 1 Ppscan parameters
+0043 101c SS 1 GE image integrity
+0043 101d SS 1 Level value
+0043 101e DS 1 Delta start time
+0043 101f SL 1 Max overranges in a view
+0043 1020 DS 1 Avg overranges all views
+0043 1021 SS 1 Corrected after glow terms
+0043 1025 SS 6 Reference channels
+0043 1026 US 6 No views ref chans blocked
+0043 1027 SH 1 Scan pitch ratio
+0043 1028 OB 1 Unique image iden
+0043 1029 OB 1 Histogram tables
+0043 102a OB 1 User defined data
+0043 102b SS 4 Private Scan Options
+0043 102c SS 1 Effective echo spacing
+0043 102d SH 1 String slop field 1
+0043 102e SH 1 String slop field 2
+0043 102f SS 1 Raw data type
+0043 1030 SS 1 Raw data type
+0043 1031 DS 2 RA cord of target recon center
+0043 1032 SS 1 Vas flags
+0043 1033 FL 1 Neg_scanspacing
+0043 1034 IS 1 Offset Frequency
+0043 1035 UL 1 User_usage_tag
+0043 1036 UL 1 User_fill_map_MSW
+0043 1037 UL 1 User_fill_map_LSW
+0043 1038 FL 24 User25...User48
+0043 1039 IS 4 Slop_int_6... slop_int_9
+0043 1040 FL 4 Trigger on position
+0043 1041 FL 4 Degree of rotation
+0043 1042 SL 4 DAS trigger source
+0043 1043 SL 4 DAS fpa gain
+0043 1044 SL 4 DAS output source
+0043 1045 SL 4 DAS ad input
+0043 1046 SL 4 DAS cal mode
+0043 1047 SL 4 DAS cal frequency
+0043 1048 SL 4 DAS reg xm
+0043 1049 SL 4 DAS auto zero
+0043 104a SS 4 Starting channel of view
+0043 104b SL 4 DAS xm pattern
+0043 104c SS 4 TGGC trigger mode
+0043 104d FL 4 Start scan to X-ray on delay
+0043 104e FL 4 Duration of X-ray on
+0043 1060 IS 8 slop_int_10...slop_int_17
+0043 1061 UI 1 Scanner Study Entity UID
+0043 1062 SH 1 Scanner Study ID
+0043 106f DS 3 Scanner Table Entry (single gradient coil systems only)
+0043 106f DS 4 Scanner Table Entry + Gradient Coil Selected
+
+0045 0000 UL 1 Group Length
+0045 0010 LO 1 Private Creator Identification (GEMS_HELIOS_01) 
+0045 1001 SS 1 Number of Macro Rows in Detector
+0045 1002 FL 1 Macro width at ISO Center
+0045 1003 SS 1 DAS type
+0045 1004 SS 1 DAS gain
+0045 1005 SS 1 DAS Temprature
+0045 1006 CS 1 Table Direction
+0045 1007 FL 1 Z smoothing Factor
+0045 1008 SS 1 View Weighting Mode
+0045 1009 SS 1 Sigma Row number
+0045 100a FL 1 Minimum DAS value
+0045 100b FL 1 Maximum Offset Value
+0045 100c SS 1 Number of Views shifted
+0045 100d SS 1 Z tracking Flag
+0045 100e FL 1 Mean Z error
+0045 100f FL 1 Z tracking Error
+0045 1010 SS 1 Start View 2A
+0045 1011 SS 1 Number of Views 2A
+0045 1012 SS 1 Start View 1A
+0045 1013 SS 1 Sigma Mode
+0045 1014 SS 1 Number of Views 1A
+0045 1015 SS 1 Start View 2B
+0045 1016 SS 1 Number Views 2B
+0045 1017 SS 1 Start View 1B
+0045 1018 SS 1 Number of Views 1B
+0045 1019 SS 1 Air Calibration Date
+0045 101a SS 1 Air Calibration Time
+0045 101b SS 1 Phantom Calibration Date
+0045 101c SS 1 Phantom Calibration Time
+0045 101d SS 1 Z Slope Calibration Date
+0045 101e SS 1 Z Slope Calibration Time
+0045 101f SS 1 Cross Talk Calibration Date
+0045 1020 SS 1 Cross Talk Calibration Time
+0045 1021 SS 1 Iterbone Flag
+0045 1022 SS 1 Perisstaltic Flag
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/HITACHI-MR-pronto.dic b/Utilities/ITK/Utilities/gdcm/Dicts/HITACHI-MR-pronto.dic
new file mode 100644
index 0000000000000000000000000000000000000000..1881b4ff9b0e75fa75cac0956663db519075f5a5
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/HITACHI-MR-pronto.dic
@@ -0,0 +1,4 @@
+0009 0000 UL 1 Group Length
+0009 0010 LO 1 Private Creator
+0009 0011 LO 1 Private Creator
+0009 1100 OB 1 Image ID Information
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/NIH.dic b/Utilities/ITK/Utilities/gdcm/Dicts/NIH.dic
new file mode 100644
index 0000000000000000000000000000000000000000..038703b9996cbfd89cec05f763c2b23682c0d4b5
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/NIH.dic
@@ -0,0 +1,15 @@
+0018 106b UI 1 Synchronization Frame of Reference (RET)
+0028 0013 US 1 Instants (RET)
+0028 0015 US 1 UsedNbX ACR Special (RET)
+0028 0016 US 1 UsedNbY ACR Special (RET)
+0028 0017 US 1 UsedNbZ ACR Special (RET)
+0028 0018 US 1 UsedNbT ACR Special (RET)
+0028 0122 US 1 Waveform Padding Value (RET)
+0028 0199 US 1 Special Code (RET)
+003a 0002 SQ 1 Waveform Sequence (RET)
+003a 0103 CS 1 Data Value Representation (RET)
+0040 0552 SQ 1 Specimen Description Sequence (RET)
+0040 0553 ST 1 Specimen Description (RET)
+0040 09f8 SQ 1 Vital Stain Code Sequence (RET)
+0040 a16a ST 1 Bibliographics Citation (RET)
+0040 a992 ST 1 Uniform Resource Locator (RET)
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/PHILIPS-EasyVision.dic b/Utilities/ITK/Utilities/gdcm/Dicts/PHILIPS-EasyVision.dic
new file mode 100644
index 0000000000000000000000000000000000000000..a41c6af108b45cde7459b43019722bc8266282a1
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/PHILIPS-EasyVision.dic
@@ -0,0 +1,3 @@
+0009 YY04 LO 1-n Image Data Consistence
+0019 YY25 LO 1-n Original Pixel Data Quality
+0029 YY25 LO 1-n Processed Pixel Data Quality
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/PHILIPS-Intera.dic b/Utilities/ITK/Utilities/gdcm/Dicts/PHILIPS-Intera.dic
new file mode 100644
index 0000000000000000000000000000000000000000..35d58bf4480eb9a5d57918a74449da60dacff400
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/PHILIPS-Intera.dic
@@ -0,0 +1,90 @@
+2001 0000 UL 1 Group Length
+2001 0010 LO 1 Private Creator Group 2001
+2001 1001 FL 1 Chemical Shift
+2001 1002 IS 1 Chemical Shift Number MR
+2001 1003 FL 1 Diffusion B-Factor
+2001 1004 CS 1 Diffusion Direction
+2001 1006 CS 1 Image Enhanced
+2001 1007 CS 1 Image Type ED ES
+2001 1008 IS 1 Phase Number
+2001 100a IS 1 Slice Number MR
+2001 100b CS 1 Slice Orientation
+2001 1011 FL 1 Diffusion Echo Time
+2001 1012 CS 1 Dynamic Series
+2001 1013 SL 1 EPI Factor
+2001 1014 SL 1 Number of Echoes
+2001 1015 SS 1 Number of Locations
+2001 1016 SS 1 Number of PC Directions
+2001 1017 SL 1 Number of Phases MR
+2001 1018 SL 1 Number of Slices MR
+2001 1019 CS 1 Partial Matrix Scanned
+2001 101a FL 1-n PC Velocity
+2001 101b FL 1 Prepulse Delay
+2001 101c CS 1 Prepulse Type
+2001 101d IS 1 Reconstruction Number MR
+2001 101f CS 1 Respiration Sync
+2001 1021 CS 1 SPIR
+2001 1022 FL 1 Water Fat Shift
+2001 1023 DS 1 Flip Angle Philips
+2001 1025 SH 1 Echo Time Display MR
+2001 102d SS 1 Stack Number of Slices
+2001 1032 FL 1 Stack Radial Angle
+2001 1033 CS 1 Stack Radial Axis
+2001 1035 SS 1 Stack Slice Number
+2001 1036 CS 1 Stack Type
+2001 103f CS 1 Zoom Mode
+2001 105f SQ 1 Stack Sequence
+2001 1060 SL 1 Number of Stacks
+2001 1063 CS 1 Examination Source
+2001 107b IS 1 Acquisition Number
+2001 1081 IS 1 Number of Dynamic Scans
+
+2001 00e0 LO 1 Private Creator Group 2001
+2001 e001 FL 1 Chemical Shift
+2001 e002 IS 1 Chemical Shift Number MR
+2001 e003 FL 1 Diffusion B-Factor
+2001 e004 CS 1 Diffusion Direction
+2001 e006 CS 1 Image Enhanced
+2001 e007 CS 1 Image Type ED ES
+2001 e008 IS 1 Phase Number
+2001 e00a IS 1 Slice Number MR
+2001 e00b CS 1 Slice Orientation
+2001 e011 FL 1 Diffusion Echo Time
+2001 e012 CS 1 Dynamic Series
+2001 e013 SL 1 EPI Factor
+2001 e014 SL 1 Number of Echoes
+2001 e015 SS 1 Number of Locations
+2001 e016 SS 1 Number of PC Directions
+2001 e017 SL 1 Number of Phases MR
+2001 e018 SL 1 Number of Slices MR
+2001 e019 CS 1 Partial Matrix Scanned
+2001 e01a FL 1-n PC Velocity
+2001 e01b FL 1 Prepulse Delay
+2001 e01c CS 1 Prepulse Type
+2001 e01d IS 1 Reconstruction Number MR
+2001 e01f CS 1 Respiration Sync
+2001 e021 CS 1 SPIR
+2001 e022 FL 1 Water Fat Shift
+2001 e023 DS 1 Flip Angle Philips
+2001 e025 SH 1 Echo Time Display MR
+2001 e02d SS 1 Stack Number of Slices
+2001 e032 FL 1 Stack Radial Angle
+2001 e033 CS 1 Stack Radial Axis
+2001 e035 SS 1 Stack Slice Number
+2001 e036 CS 1 Stack Type
+2001 e03f CS 1 Zoom Mode
+2001 e05f SQ 1 Stack Sequence
+2001 e060 SL 1 Number of Stacks
+2001 e063 CS 1 Examination Source
+2001 e07b IS 1 Acquisition Number
+2001 e081 IS 1 Number of Dynamic Scans
+
+2005 0000 UL 1 Group Length
+2005 0010 LO 1 Private Creator Group 2005
+2005 1005 CS 1 Synergy Reconstruction Type
+2005 1020 SL 1 Number of Chemical Shifts
+2005 10a1 CS 1 Syncra Scan Type
+
+2005 1083 SQ 1 Temporary SQ 1
+2005 1402 SQ 1 Temporary SQ 2
+
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/Papyrus.dic b/Utilities/ITK/Utilities/gdcm/Dicts/Papyrus.dic
new file mode 100644
index 0000000000000000000000000000000000000000..ee8ffad255070a407184e113ece02de5b4d3cd06
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/Papyrus.dic
@@ -0,0 +1,16 @@
+0041 0000 UL 1 Group Length
+0041 0010 LO 1 Owner ID (PAPYRUS 3.0)
+0041 1000 LT 1 Comments
+0041 1010 SQ 1 Pointer Sequence
+0041 1011 UL 1 Image Pointer
+0041 1012 UL 1 Pixel Offset
+0041 1013 SQ 1 Image Identifier Sequence
+0041 1014 SQ 1 External PAPYRUS-File Reference Sequence
+0041 1015 US 1 Number of images
+0041 1021 UI 1 Referenced SOP Class UID
+0041 1022 UI 1 Referenced SOP Instance UID
+0041 1031 LO 1 Referenced File Name
+0041 1032 LO 1-n Referenced File Path
+0041 1041 UI 1 Referenced Image SOP Class UID
+0041 1042 UI 1 Referenced Image SOP Instance UID
+0041 1050 SQ 1 Image Sequence
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/ParseDict.py b/Utilities/ITK/Utilities/gdcm/Dicts/ParseDict.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b3924245ab53897026a32b625fb2b949786f117
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/ParseDict.py
@@ -0,0 +1,735 @@
+#! /usr/bin/env python
+"""
+Let's write our own python parser to clean up the pdf (after 
+pdftotext of course). 
+Instructions: run pdftotext like this:
+
+$ pdftotext -f 9 -l 81 -raw -nopgbrk 04_06PU.PDF 04_06PU-3.txt
+
+then run the python parser like this:
+
+$ python ParseDict.py 04_06PU.txt dicomV3.dic
+"""
+import re,os
+
+"""
+PdfTextParser takes as input a text file (produced by pdftotext)
+and create as output a clean file (ready to be processed) by
+DicomV3Expander
+Warning: PdfTextParser does not expand:
+- (xxxx,xxxx to xxxx) xxxxxxxxxxxx
+or
+- (12xx, 3456) comment...
+
+"""
+class PdfTextParser:
+  # Cstor
+  def __init__(self):
+    self._InputFilename = ''
+    self._OutputFilename = ''
+    self._Infile = 0
+    self._OutLines = []
+    self._PreviousBuffers = []
+
+  def SetInputFileName(self,s):
+    self._InputFilename = s
+
+  def SetOutputFileName(self,s):
+    self._OutputFilename = s
+  
+  # Function returning if s is a comment for sure
+  def IsAComment(self,s):
+    #print s,  len(s)
+    if s == "Tag Name VR VM":
+      return True
+    elif s == "PS 3.6-2003":
+      return True
+    elif s == "PS 3.6-2004":
+      return True
+    patt = re.compile('^Page [0-9]+$') 
+    if( patt.match(s) ):
+      return True
+    return False
+
+  def IsAStartingLine(self,s):
+    patt = re.compile('^\\([0-9a-fA-Fx]+,[0-9a-fA-F]+\\) (.*)$') 
+    if( patt.match(s) ):
+      return True
+    return False
+
+  def IsAFullLine(self,s):
+    patt = re.compile('^\\([0-9a-fA-Fx]+,[0-9a-fA-F]+\\) (.*) [A-Z][A-Z] [0-9]$')
+    if( patt.match(s) ):
+      return True
+    return False
+
+  # FIXME this function could be avoided...
+  def IsSuspicious(self,s):
+    l = len(s)
+    if l > 80:
+      return True
+    return False
+
+  def AddOutputLine(self,s):
+    assert not self.IsAComment(s)
+    self._OutLines.append(s + '\n')
+
+  def Open(self):
+    self._Infile = file(self._InputFilename, 'r')
+    for line in self._Infile.readlines():
+      line = line[:-1] # remove '\n'
+      if not self.IsAComment( line ):
+        if self.IsAStartingLine(line):
+          #print "Previous buffer:",self._PreviousBuffers
+          previousbuffer = ' '.join(self._PreviousBuffers)
+          if self.IsAStartingLine(previousbuffer):
+            if not self.IsSuspicious(previousbuffer):
+              self.AddOutputLine(previousbuffer)
+            else:
+              # this case should not happen if I were to rewrite the
+              # thing I should be able to clean that
+              #print "Suspicious:", previousbuffer
+              #print "List is:", self._PreviousBuffers
+              s = self._PreviousBuffers[0]
+              if self.IsAFullLine(s):
+                # That means we have a weird line that does not start
+                # as usual (xxxx,xxxx) therefore we tried constructing
+                # a buffer using a the complete previous line...
+                #print "Full line:", s
+                self.AddOutputLine(s)
+                s2 = ' '.join(self._PreviousBuffers[1:])
+                #print "Other Full line:", s2
+                self.AddOutputLine(s2)
+              else:
+                # we have a suspicioulsy long line, so what that could
+                # happen, let's check:
+                if self.IsAFullLine(previousbuffer):
+                  self.AddOutputLine(previousbuffer)
+                else:
+                  # This is the only case where we do not add
+                  # previousbuffer to the _OutLines
+                  print "Suspicious and Not a full line:", s
+          else:
+            if previousbuffer:
+              print "Not a buffer:", previousbuffer
+          # We can clean buffer, since only the case 'suspicious' +
+          # 'Not a full line' has not added buffer to the list
+          self._PreviousBuffers = []
+          # In all cases save the line for potentially growing this line
+          assert not self.IsAComment(line)
+          self._PreviousBuffers.append(line)
+        else:
+          #print "Not a line",line
+          assert not self.IsAComment(line)
+          self._PreviousBuffers.append(line)
+      else:
+        #print "Comment:",line
+        previousbuffer = ' '.join(self._PreviousBuffers)
+        if previousbuffer and self.IsAStartingLine(previousbuffer):
+          #print "This line is added:", previousbuffer
+          self.AddOutputLine( previousbuffer )
+        else:
+          #print "Line is comment:", line
+          print "Buffer is:", previousbuffer
+        # Ok this is a comment we can safely clean the buffer:
+        self._PreviousBuffers = []
+    self.Write()
+
+  def Write(self):
+    outfile = file(self._OutputFilename, 'w')
+    outfile.writelines( self._OutLines )
+    outfile.close()
+    self._Infile.close()
+    
+  # Main function to call for parsing
+  def Parse(self):
+    self.Open()
+
+"""
+subclass
+"""
+class UIDParser(PdfTextParser):
+  def IsAStartingLine(self,s):
+    patt = re.compile('^1.2.840.10008.[0-9.]+ (.*)$') 
+    if( patt.match(s) ):
+      return True
+    #print "Is Not:", s
+    return False
+
+  def IsAFullLine(self,s):
+    patt = re.compile('^1.2.840.10008.[0-9.]+ (.*) PS ?[0-9].1?[0-9]$') 
+    if( patt.match(s) ):
+      return True
+    patt = re.compile('^1.2.840.10008.[0-9.]+ (.*) Well-known frame of reference$') 
+    if( patt.match(s) ):
+      return True
+    patt = re.compile('^1.2.840.10008.[0-9.]+ (.*) \\(Retired\\)$') 
+    if( patt.match(s) ):
+      return True
+    return False
+
+  def IsAComment(self,s):
+    if PdfTextParser.IsAComment(self,s):
+      return True
+    # else let's enhance the super class
+    patt = re.compile('^SPM2 (.*) http(.*)$') 
+    if( patt.match(s) ):
+      return True
+    return False
+
+  def AddOutputLine(self,s):
+    if self.IsAFullLine(s):
+      return PdfTextParser.AddOutputLine(self,s)
+    print "Discarding:", s
+
+
+"""
+TransferSyntaxParser
+"""
+class TransferSyntaxParser(UIDParser):
+  def IsAFullLine(self,s):
+    patt = re.compile('^(.*) Transfer Syntax PS ?[0-9].1?[0-9]$') 
+    if patt.match(s):
+      return UIDParser.IsAStartingLine(self,s)
+    print "Not a TS:", s
+    return False
+    
+"""
+Papyrus parser
+pdftotext -f 19 -l 41 -raw -nopgbrk /tmp/Papyrus31Specif.pdf /tmp/Papyrus31Specif.txt 
+
+I need to do a second pass for pages:
+#29 since I need to find [0-9.]+
+#40,41 since it start with number in two columns !!
+""" 
+class PapyrusParser(PdfTextParser):
+  def __init__(self):
+    self._PreviousPage = 0
+    self._PreviousNumber = 0
+    PdfTextParser.__init__(self)
+
+  def IsAStartingLine(self,s):
+    patt = re.compile('^[A-Za-z \'\(\)]+ +\\([0-9A-F]+,[0-9A-F]+\\) +(.*)$') 
+    if( patt.match(s) ):
+      return True
+    # After page 39, lines are like:
+    patt = re.compile('^[0-9x]+ [0-9xA-F]+ .*$') 
+    if( patt.match(s) ):
+      #print "PAge 39", s
+      return True
+    return False
+
+  def IsAFullLine(self,s):
+    patt = re.compile('^[A-Za-z \'\(\)]+ +\\([0-9A-F]+,[0-9A-F]+\\) +(.*)$') 
+    if( patt.match(s) ):
+      return True
+    # After page 39, lines are like:
+    patt = re.compile('^[0-9x]+ [0-9xA-F]+ .* [A-Z][A-Z] [0-9].*$') 
+    if( patt.match(s) ):
+      #print "PAge 39", s
+      return True
+    return False
+
+  def IsAComment(self,s):
+    # dummy case:
+    if s == 'Attribute Name Tag Type Attribute Description':
+      #print "Dummy", s
+      return True
+    patt = re.compile('^.*ANNEXE.*$')
+    if patt.match(s):
+      return True
+    # Indicate page #, spaces ending with only one number
+    # Sometime there is a line with only one number, we need to
+    # make sure that page # is strictly increasing
+    patt = re.compile('^[1-9][0-9]+$') 
+    if( patt.match(s) ):
+      p = eval(s)
+      if( p > self._PreviousPage):
+        #print "Page #", p
+        self._PreviousNumber = 0
+        self._PreviousPage = p
+        return True
+#      else:
+#        print "PAGE ERROR:", s
+    # Now within each page there is a comment that start with a #
+    # let's do the page approach wich reset at each page
+    patt = re.compile('^[0-9]+$') 
+    if( patt.match(s) ):
+      if( eval(s) > self._PreviousNumber):
+        #print "Number #", eval(s)
+        self._PreviousNumber = eval(s)
+        return True
+      #else:
+      #  print "ERROR:", s
+    return False
+
+  def AddOutputLine(self,s):
+    assert not self.IsAComment(s)
+    s = s.replace('\n','')
+    #print "REMOVE return:", s
+    patt = re.compile('^([A-Za-z \'\(\)]+) (\\([0-9A-F]+,[0-9A-F]+\\)) ([0-9C]+) (.*)$') 
+    m = patt.match(s)
+    ss = 'dummy (0000,0000) 0'
+    if m:
+      ss = m.group(2) + ' ' + m.group(3) + ' ' + m.group(1)
+    else:
+      patt = re.compile('^([A-Za-z \'\(\)]+) (\\([0-9A-F]+,[0-9A-F]+\\)) (.*)$') 
+      m = patt.match(s)
+      if m:
+        ss = m.group(2) + ' 0 ' + m.group(1)
+      else:
+        ss = s
+        # There is two case one that end with all capital letter
+        # explaining the 'DEFINED TERMS'
+        patt = re.compile('^[0-9x]+ [0-9xA-F]+ .* [A-Z][A-Z] [0-9] [A-Z, ]$') 
+        #patt = re.compile('^[0-9x]+ [0-9xA-F]+ .* [A-Z][A-Z] [0-9]|1\\-n [A-Z, |3.0]+$') 
+        #patt = re.compile('^[0-9x]+ [0-9xA-F]+ .* [A-Z][A-Z] [01n-] [A-Z, |3.0]+$') 
+        if patt.match(s):
+          print "Match", s
+          ss = ''
+    self._OutLines.append(ss + '\n')
+
+  def Open(self):
+    self._Infile = file(self._InputFilename, 'r')
+    for line in self._Infile.readlines():
+      line = line[:-1] # remove '\n'
+      if not self.IsAComment( line ):
+        if self.IsAStartingLine(line):
+          #print "Previous buffer:",self._PreviousBuffers
+          previousbuffer = ' '.join(self._PreviousBuffers)
+          if self.IsAFullLine(previousbuffer):
+            self.AddOutputLine(previousbuffer)
+          else:
+            if previousbuffer:
+              print "Not a buffer:", previousbuffer
+          # We can clean buffer, since only the case 'suspicious' +
+          # 'Not a full line' has not added buffer to the list
+          self._PreviousBuffers = []
+          # In all cases save the line for potentially growing this line
+          # just to be safe remove any white space at begining of string
+          assert not self.IsAComment(line)
+          self._PreviousBuffers.append(line.strip())
+        else:
+          #print "Not a line",line
+          assert not self.IsAComment(line)
+          # just to be safe remove any white space at begining of string
+          self._PreviousBuffers.append(line.strip())
+      else:
+        #print "Previous buffer:",self._PreviousBuffers
+        previousbuffer = ' '.join(self._PreviousBuffers)
+        if previousbuffer and self.IsAStartingLine(previousbuffer):
+          #print "This line is added:", previousbuffer
+          self.AddOutputLine( previousbuffer )
+#        else:
+#          #print "Line is comment:", line
+#          print "Buffer is:", previousbuffer
+        # Ok this is a comment we can safely clean the buffer:
+        self._PreviousBuffers = []
+    self.Write()
+
+"""
+Parser for:
+GE Medical Systems HISPEED ADVANTAGE CT/i CONFORMANCE STATEMENT
+pdftotext -f 81 -l 90 -raw -nopgbrk 2162114_100r5.pdf 2162114_100r5.txt
+"""
+class GEMSParser(PdfTextParser):
+#  def __init__(self):
+#    PdfTextParser.__init__(self)
+
+  def IsAStartingLine(self,s):
+    #patt = re.compile('^[A-Za-z \'\(\)]+ +\\([0-9A-F]+,[0-9A-F]+\\) +(.*)$') 
+    patt = re.compile('^[A-Za-z0-9 .#(),_/-]+ +\\([0-9A-F]+, ?[0-9A-F]+\\) +(.*)$')
+    if( patt.match(s) ):
+      return True
+    return False
+
+  def IsAFullLine(self,s):
+    #patt = re.compile('^[A-Za-z \'\(\)]+ +\\([0-9A-F]+,[0-9A-F]+\\) +(.*)$') 
+    patt = re.compile('^[A-Za-z0-9 .#(),_/-]+ +\\([0-9A-F]+, ?[0-9A-F]+\\) [A-Z][A-Z] [0-9]+$') 
+    if( patt.match(s) ):
+      return True
+    print "Not full:", s
+    return False
+
+  def IsAComment(self,s):
+    if PdfTextParser.IsAComment(self,s):
+      return True
+    #patt = re.compile('^.*GE Medical Systems LightSpeed QX/i CONFORMANCE STATEMENT REV 2.2 sm 2288567-100.*$')
+    #if patt.match(s):
+    #  return True
+    patt = re.compile('^.*GE Medical Systems HISPEED ADVANTAGE CT/i CONFORMANCE STATEMENT.*$') 
+    if patt.match(s):
+      return True
+    patt = re.compile('^GE Medical Systems LightSpeed QX/i CONFORMANCE STATEMENT.*$')
+    if patt.match(s):
+      return True
+    patt = re.compile('^Attribute Name Tag VR VM$')
+    if patt.match(s):
+      return True
+    patt = re.compile('^B.[1-9].*Private .*$')
+    if patt.match(s):
+      return True
+    patt = re.compile('^Table B.1.? .* Private .*$')
+    if patt.match(s):
+      return True
+    patt = re.compile('^Note :.*$')
+    if patt.match(s):
+      return True
+    patt = re.compile('^7.11.1$')
+    if patt.match(s):
+      return True
+    return False
+
+  def AddOutputLine(self,s):
+    #print s
+    assert not self.IsAComment(s)
+    patt = re.compile('^([A-Za-z0-9 .#(),_/-]+) +\\(([0-9A-F]+), ?([0-9A-F]+)\\) ([A-Z][A-Z]) ([0-9]+)$') 
+    m = patt.match(s)
+    if m:
+      ss = m.group(2).lower() + ' ' + m.group(3).lower() + ' ' + m.group(4) + ' ' + m.group(5) + ' ' + m.group(1)
+      self._OutLines.append(ss + '\n')
+    else:
+      print 'OOOPs', s
+
+
+"""
+This class is meant to expand line like:
+- (xxxx,xxxx to xxxx) xxxxxxxxxxxx
+or
+- (12xx, 3456) comment...
+
+"""
+class DicomV3Expander:
+  def __init__(self):
+    self._InputFilename = ''
+    self._OutputFilename = ''
+    self._OutLines = []
+
+  def SetInputFileName(self,s):
+    self._InputFilename = s
+
+  def SetOutputFileName(self,s):
+    self._OutputFilename = s
+ 
+  # Function to turn into lower case a tag:
+  # ex: (ABCD, EF01) -> (abcd, ef01)
+  def LowerCaseTag(self,s):
+    #print "Before:", s[:-1]
+    patt = re.compile('^(\\([0-9a-fA-F]+,[0-9a-fA-F]+\\))(.*)$')
+    m = patt.match(s)
+    if m:
+      s1 = m.group(1)
+      s2 = m.group(2)
+      return s1.lower() + s2
+    else:
+      patt = re.compile('^[0-9a-fA-F]+ [0-9a-fA-F]+ [A-Z][A-Z] [0-9n-] .*$')
+      if patt.match(s):
+        return s
+      else:
+        print "Impossible case:", s
+        os.sys.exit(1)
+
+  def AddOutputLine(self,s):
+    if s.__class__ == list:
+      for i in s:
+        self._OutLines.append(i + '\n')
+    else:
+      self._OutLines.append(s + '\n')
+
+  # Expand the line approriaetkly and also add it to the
+  # _OutLines list
+  def ExpandLine(self, s):
+    assert s[-1] == '\n'
+    s = s[:-1]  # remove \n
+    list = []
+    if self.NeedToExpansion(s, list):
+      self.AddOutputLine(list) # list != []
+    elif self.NeedGroupXXExpansion(s, list):
+      self.AddOutputLine(list) # list != []
+    elif self.NeedElemXXExpansion(s, list):
+      self.AddOutputLine(list) # list != []
+    else:
+      self.AddOutputLine(self.LowerCaseTag(s))
+
+  # If line is like:
+  # (0020,3100 to 31FF) Source Image Ids RET
+  def NeedToExpansion(self,s, list):
+    patt = re.compile('^\\(([0-9a-fA-F]+),([0-9a-fA-F]+) to ([0-9a-fA-F]+)\\)(.*)$')
+    m = patt.match(s)
+    if m:
+      #print m.groups()
+      gr = m.group(1)
+      el_start = '0x'+m.group(2)
+      el_end = '0x'+m.group(3)
+      for i in range(eval(el_start), eval(el_end)):
+        el = hex(i)[2:]
+        l = '('+gr+','+el+')'+m.group(4)
+        list.append(l)
+      return True
+    return False
+
+  # If line is like:
+  # (50xx,1200) Number of Patient Related Studies IS 1
+  def NeedGroupXXExpansion(self,s,list):
+    patt = re.compile('^\\(([0-9a-fA-F]+)xx,([0-9a-fA-F]+)\\)(.*)$')
+    m = patt.match(s)
+    if m:
+      #print m.groups()
+      gr_start = m.group(1)
+      el = m.group(2)
+      #el_start = '0x'+m.group(2)
+      #el_end = '0x'+m.group(3)
+      start = '0x'+gr_start+'00'
+      end   = '0x'+gr_start+'FF'
+      for i in range(eval(start), eval(end)):
+        gr = hex(i)[2:]
+        l = '('+gr+','+el+')'+m.group(3)
+        #print l
+        list.append(l)
+      return True
+    return False
+
+  # If line is like:
+  # (2001,xx00) Number of Patient Related Studies IS 1
+  def NeedElemXXExpansion(self,s,list):
+    patt = re.compile('^([0-9a-fA-F]+) ([0-9a-fA-F]+)xx(.*)$')
+    m = patt.match(s)
+    if m:
+      #print m.groups()
+      gr = m.group(1)
+      el_start = m.group(2)
+      start = '0x00'
+      end   = '0xFF'
+      for i in range(eval(start), eval(end)):
+        el = '%02x'% i
+        l = '('+gr+','+el_start+el+')'+m.group(3)
+        print l
+        list.append(l)
+      return True
+    else:
+      patt = re.compile('^([0-9a-fA-F]+) xx([0-9a-fA-F]+)(.*)$')
+      m = patt.match(s)
+      if m:
+        #print m.groups()
+        gr = m.group(1)
+        el_start = m.group(2)
+        start = '0x00'
+        end   = '0xFF'
+        for i in range(eval(start), eval(end)):
+          el = '%02x'% i
+          l = '('+gr+','+el+el_start+')'+m.group(3)
+          print l
+          list.append(l)
+        return True
+    return False
+
+  def Write(self):
+    outfile = file(self._OutputFilename, 'w')
+    outfile.writelines( self._OutLines )
+    outfile.close()
+
+  def Expand(self):
+    infile = file(self._InputFilename,'r')
+    for line in infile.readlines():
+      # ExpandLine also LowerCase the line
+      self.ExpandLine(line) # l is [1,n] lines
+    self.Write()
+    infile.close()
+
+"""
+Parse line from a philips document, line are like this:
+
+Syncra Scan Type 2005,10A1 VR = CS, VM = 1
+"""
+class InteraParser:
+  def __init__(self):
+    self._InputFilename = ''
+    self._OutputFilename = ''
+
+  def Reformat(self,s):
+    assert self.IsGood(s)
+    patt = re.compile("^([A-Za-z0-9 -]+) ([0-9A-Z]+),([0-9A-Z]+) VR = ([A-Z][A-Z]), VM = (.*)$")
+    m = patt.match(s)
+    if m:
+      dicom = m.group(2) + ' ' + m.group(3) + ' ' + m.group(4) + ' ' + m.group(5) + ' ' + m.group(1)
+      return dicom
+    else:
+      print "oops"
+
+  def IsGood(self,s):
+    patt = re.compile("^[A-Za-z0-9 -]+ [0-9A-Z]+,[0-9A-Z]+ VR = [A-Z][A-Z], VM = .*$")
+    if patt.match(s):
+      return True
+    print "Not good:", s
+    return False
+
+  def SetInputFileName(self,s):
+    self._InputFilename = s
+
+  def SetOutputFileName(self,s):
+    self._OutputFilename = s
+  
+  def Parse(self):
+    infile = file(self._InputFilename, 'r')
+    outLines = []
+    for line in infile.readlines():
+      print self.Reformat(line)
+      outLines.append( self.Reformat(line) + '\n' )
+    outfile = file(self._OutputFilename, 'w')
+    outfile.writelines( outLines )
+    outfile.close()
+ 
+"""
+Parse line from a dicom3tools document, line are like this:
+
+(0003,0008) VERS="SSPI" VR="US"   VM="1"        Owner="SIEMENS ISI"             Keyword="ISICommandField"                       Name="ISI Command Field"
+"""
+class Dicom3ToolsParser:
+  def __init__(self):
+    self._InputFilename = ''
+    self._OutputFilename = ''
+
+  def Reformat(self,s):
+    assert self.IsGood(s)
+    patt = re.compile("^\(([0-9a-f]+),([0-9a-f]+)\)\s+VERS=\".*\"\s+VR=\"([A-Z][A-Z])\"\s+VM=\"(.*)\"\s+Owner=\".*\"\s+Keyword=\".*\"\s+Name=\"(.*)\"$")
+    m = patt.match(s)
+    dicom = ''
+    if m:
+      # Apparently some have Name == '?', skip those
+      name = m.group(5)
+      if name != '?' and name != '? ':
+        dicom = m.group(1) + ' ' + m.group(2) + ' ' + m.group(3) + ' ' + m.group(4) + ' ' + m.group(5)
+      else:
+        print "oops"
+    else:
+      print "oops"
+    return dicom
+
+  def IsGood(self,s):
+    #patt = re.compile("^\([0-9a-f]+,[0-9a-f]+\) VERS=\".*\" VR=\"[A-Z][A-Z]\" VM=\".*\" Owner=\".*\" Keyword=\".*\" Name=\".*\"$")
+    patt = re.compile("^\([0-9a-f]+,[0-9a-f]+\)\s+VERS=\".*\"\s+VR=\"[A-Z][A-Z]\"\s+VM=\".*\"\s+Owner=\".*\"\s+Keyword=\".*\"\s+Name=\".*\".*$")
+    if patt.match(s):
+      return True
+    print "Not good:", s
+    return False
+
+  def SetInputFileName(self,s):
+    self._InputFilename = s
+
+  def SetOutputFileName(self,s):
+    self._OutputFilename = s
+  
+  def Parse(self):
+    infile = file(self._InputFilename, 'r')
+    outLines = []
+    for line in infile.readlines():
+      newline = self.Reformat(line)
+      print newline
+      if newline:
+        outLines.append( newline + '\n' )
+    outfile = file(self._OutputFilename, 'w')
+    outfile.writelines( outLines )
+    outfile.close()
+ 
+"""
+Parse line from a PhilipsAdvance document, line are like this:
+
+GE Advance Implementation Version Name (0009,1001) 3 LO 2 n/a
+"""
+class GEAdvanceParser:
+  def __init__(self):
+    self._InputFilename = ''
+    self._OutputFilename = ''
+
+  def Reformat(self,s):
+    assert self.IsGood(s)
+    #patt = re.compile("^\(([0-9a-f]+),([0-9a-f]+)\)\s+VERS=\".*\"\s+VR=\"([A-Z][A-Z])\"\s+VM=\"(.*)\"\s+Owner=\".*\"\s+Keyword=\".*\"\s+Name=\"(.*)\"$")
+    patt = re.compile("^([A-Za-z0-9 ._>]+) \\(([0-9A-F]+),([0-9A-F]+)\\) [0-9] ([A-Z][A-Z]) ([0-9]) .*$")
+    m = patt.match(s)
+    dicom = ''
+    if m:
+      dicom = m.group(2) + ' ' + m.group(3).lower() + ' ' + m.group(4) + ' ' + m.group(5) + ' ' + m.group(1)
+    else:
+      print "oops"
+    return dicom
+
+  def IsGood(self,s):
+    #patt = re.compile("^\([0-9a-f]+,[0-9a-f]+\)\s+VERS=\".*\"\s+VR=\"[A-Z][A-Z]\"\s+VM=\".*\"\s+Owner=\".*\"\s+Keyword=\".*\"\s+Name=\".*\".*$")
+    patt = re.compile("^[A-Za-z0-9 ._>]+ \\([0-9A-F]+,[0-9A-F]+\\) [0-9] [A-Z][A-Z] [0-9] .*$")
+    if patt.match(s):
+      return True
+    print "Not good:", s
+    return False
+
+  def SetInputFileName(self,s):
+    self._InputFilename = s
+
+  def SetOutputFileName(self,s):
+    self._OutputFilename = s
+  
+  def Parse(self):
+    infile = file(self._InputFilename, 'r')
+    outLines = []
+    for line in infile.readlines():
+      newline = self.Reformat(line)
+      #print newline
+      if newline:
+        outLines.append( newline + '\n' )
+    outfile = file(self._OutputFilename, 'w')
+    outfile.writelines( outLines )
+    outfile.close()
+ 
+if __name__ == "__main__":
+  argc = len(os.sys.argv )
+  if ( argc < 3 ):
+    print "Sorry, wrong list of args"
+    os.sys.exit(1) #error
+
+  inputfilename = os.sys.argv[1]
+  outputfilename = os.sys.argv[2]
+  tempfile = "/tmp/mytemp"
+  """
+  dp = PdfTextParser()
+  dp.SetInputFileName( inputfilename )
+  #dp.SetOutputFileName( outputfilename )
+  dp.SetOutputFileName( tempfile )
+  dp.Parse()
+  exp = DicomV3Expander()
+  #exp.SetInputFileName( tempfile )
+  exp.SetInputFileName( inputfilename )
+  exp.SetOutputFileName( outputfilename )
+  exp.Expand()
+
+  dp = TransferSyntaxParser()
+  dp.SetInputFileName( inputfilename )
+  dp.SetOutputFileName( outputfilename )
+  dp.Parse()
+
+  dp = PapyrusParser()
+  dp.SetInputFileName( inputfilename )
+  dp.SetOutputFileName( outputfilename )
+  dp.Parse()
+
+  dp = InteraParser()
+  dp.SetInputFileName( inputfilename )
+  dp.SetOutputFileName( outputfilename )
+  dp.Parse()
+  dp = GEMSParser()
+  dp.SetInputFileName( inputfilename )
+  dp.SetOutputFileName( outputfilename )
+  dp.Parse()
+
+  """
+  dp = Dicom3ToolsParser()
+  dp.SetInputFileName( inputfilename )
+  dp.SetOutputFileName( outputfilename )
+  dp.Parse()
+
+  """
+  dp = GEAdvanceParser()
+  dp.SetInputFileName( inputfilename )
+  dp.SetOutputFileName( outputfilename )
+  dp.Parse()
+  """
+
+  #print dp.IsAStartingLine( "(0004,1212) File-set Consistency Flag US 1\n" )
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/README b/Utilities/ITK/Utilities/gdcm/Dicts/README
new file mode 100644
index 0000000000000000000000000000000000000000..6f94c6ec9985c35738f491459d24021208dc7df1
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/README
@@ -0,0 +1,321 @@
+Sources for dicom public dictionaries:
+ * the official source is the part 6 of the dicom standard (see
+   http://www.dclunie.com/dicom-status/status.html#BaseStandard2001).
+ * http://www.fpimage.com/Manuals/Imp/dicomdic.html
+   an html group based presentation.
+ * ftp://rsbweb.nih.gov/pub/nih-image/documents/dicom-dict.txt
+   a C syntax oriented version provided by NIH (Jim Nash)
+ * http://afni.nimh.nih.gov/afni/AFNI_Dist/afni_src.tgz
+   extract mri_dicom_hdr.c (tar zxvf afni_src.tgz afni_src/mri_dicom_hdr.c)
+   and look for the definitions of CMD_dictionary, META_dictionary,
+   ID_dictionary, PAT_dictionary...
+ * Actually, the *official* Dicom Data Dictionary 
+   is on http://medical.nema.org/dicom/2003/03_06PU.pdf
+   (check it every year, some tags are added, some names change)
+   All C syntax oriented stuff, or anything else -but gdcm one-
+   you can find on the net is very partial.
+   WARNING : The Dicom Tag is an identifier inside the Dicom Dictionary,
+             The Tag Name *is not*
+
+
+Comment on the file NIH.dic, you can find the following discussion
+on comp.protocol.dicom(*). As clearly specify by David Clunie all
+thoses tags are extremely dangerous to use since they override some
+other, we are only adding them to gdcm to be able to read /apparently/
+some NIH images. SHOULD NOT EVER BE USED FOR WRITTING IMAGES !
+
+(*)
+[Re: Retired element VR and VM, was Re: 0028,3006 LUT Data (nightmare)]
+...
+> 'gdcm' Dicom dictionary uses a few tags, such as :
+>  0018 106b UI 1 Synchronization Frame of Reference
+This should be:
+(0020,0200) Synchronization Frame of Reference UID
+>  0028 0122 US 1 Waveform Padding Value
+(5400,100A)    Waveform Padding Value
+>   003a 0002 SQ 1 Waveform Sequence
+(5400,0100)    Waveform Sequence
+>   003a 0103 CS 1 Data Value Representation
+(50xx,0103)    Data Value Representation
+>   0040 0552 SQ 1 Specimen Description Sequence
+No such attribute
+>   0040 0553 ST 1 Specimen Description
+No such attribute
+>   0040 09f8 SQ 1 Vital Stain Code Sequence
+No such attribute
+>   0040 a16a ST 1 Bibliographics Citation
+No such attribute
+>   0040 a992 ST 1 Uniform Resource Locator
+No such attribute
+
+I suspect these were taken for the draft for trial implementation
+of Sup 23 SR, which was problematic in many ways, not the least
+of which was that some of its attributes with the same number
+were re-used with different purpose and VR, etc.
+
+Some may have been from early drafts of other supplements (e.g.,
+waveform from the looks of things).
+
+None of these should ever be used. 
+...
+
+
+
+
+
+
+Remarks about dicomV3Intera.dic:
+
+This document is produced /somehow/ using document at:
+[Intera 10.1]
+http://www.medical.philips.com/main/company/connectivity/assets/docs/dicomcs/Conformance_Statement_MR_101_v04.pdf
+
+[DICOM Conformance Statement]
+http://www.medical.philips.com/main/company/connectivity/assets/docs/dicomcs/MR_InteraR104dcs.pdf
+
+
+Remarks about GEMS.dic
+
+This document is produced using:
+GE Medical Systems HISPEED ADVANTAGE CT/i CONFORMANCE STATEMENT:
+http://www.gehealthcare.com/euen/interoperability/docs/2162114_100r5.pdf
+
+the 0023 tags were also extracted from:
+[Technical Publications]
+http://www.gehealthcare.com/usen/interoperability/dicom/docs/22046092.pdf
+
+Ok I finally understood the Private Creator thing:
+V 0025|0010 lg :       x(c) 12       Off.:     x(e4e) 3662    [LO]                                                      [gdcm::Unknown] [GEMS_SERS_01]
+V 0027|0010 lg :       x(c) 12       Off.:     x(eda) 3802    [LO]                                                      [gdcm::Unknown] [GEMS_IMAG_01]
+V 0029|0010 lg :       x(c) 12       Off.:    x(10b8) 4280    [LO]                                                      [gdcm::Unknown] [GEMS_IMPS_01]
+V 0043|0010 lg :       x(c) 12       Off.:    x(112a) 4394    [LO]                                                      [gdcm::Unknown] [GEMS_PARM_01]
+
+And if you take document:
+http://www.gehealthcare.com/euen/interoperability/docs/2288567_100r3_0.pdf
+they are all described:
+
+B.2.5 Private Creator Identification (GEMS_STDY_01)
+B.2.6 Private Creator Identification (GEMS_SERS_01)
+B.2.7 Private Creator Identification (GEMS_IMAG_01)
+...
+
+In fact the best document is:
+LightSpeed QX/i 1.2 Conformance Statement for DICOM v3.0 (ID/Net v3.0) 
+http://www.gehealthcare.com/euen/interoperability/docs/2288567_100r3_0.pdf
+
+
+I was searching for 0043 1039, I could only find:
+http://www.gehealthcare.com/it_solutions/connectivity/pdf/hispeed_np.pdf
+ok -> http://www.gehealthcare.com/usen/interoperability/dicom/docs/hispeed_np.pdf
+but the link points nowhere, the document describes:
+HiSpeed LX/i, FX/i, DX/i, DX/iB 2.00/2.01/2.02 CONFORMANCE STATEMENT for DICOM v3.0
+
+..let's use google cache... not fun !
+
+
+0043 1060 was found at: http://www.gehealthcare.com/it_solutions/connectivity/pdf/2246181r25.pdf
+ok -> http://www.gehealthcare.com/usen/interoperability/dicom/docs/2246181r25.pdf
+0043 1060 IS 8 slop_int_10...slop_int_17
+
+I would also need:
+Signa Horizon Lx DICOM CONFORMANCE STATEMENT for DICOM v3.0
+grrrr: Vas flags 0043 1032 SS 1 in http://www.vitalcom.com/it_solutions/connectivity/pdf/2317752r3.pdf
+ok: -> www.gehealthcare.com/usen/interoperability/dicom/docs/2317752r3.pdf
+but 0043 1032 SS 1 Raw data type http://www.vitalcom.com/it_solutions/connectivity/pdf/2171143r25.pdf
+ok -> www.gehealthcare.com/usen/interoperability/dicom/docs/2171143r25.pdf
+
+Adding a page from : http://www.vitalcom.com/it_solutions/connectivity/pdf/2317752r3.pdf
+ 
+A Coord of Top Right Corner (0027,1049) FL 1 
+S Coord of Top Right Corner (0027,104A) FL 1 
+R Coord of Bottom Right Corner (0027,104B) FL 1 
+A Coord of Bottom Right Corner (0027,104C) FL 1 
+S Coord of Bottom Right Corner (0027,104D) FL 1 
+Image dimension - X (0027,1060) FL 1 
+Image dimension - Y (0027,1061) FL 1 
+Number of Excitations (0027,1062) FL 1 
+B.1. 8 Private Creator Identification (GEMS_IMPS_01) 
+Lower range of Pixels1 (0029,1015) SL 1 
+Lower range of Pixels1 (0029,1016) SL 1 
+Lower range of Pixels2 (0029,1017) SL 1 
+Upper range of Pixels2 (0029,1018) SL 1 
+Len of tot hdr in bytes (0029,101A) SL 1 
+Version of the hdr struct (0029,1026) SS 1 
+Advantage comp. Overflow (0029,1034) SL 1 
+Advantage comp. Underflow (0029,1035) SL 1 
+B.1. 9 Private Creator Identification (GEMS_PARM_01) 
+Bitmap of prescan options (0043,1001) SS 1 
+Gradient offset in X (0043,1002) SS 1 
+Gradient offset in Y (0043,1003) SS 1 
+Gradient offset in Z (0043,1004) SS 1 
+Img is original or unoriginal (0043,1005) SS 1 
+Number of EPI shots (0043,1006) SS 1 
+Views per segment (0043,1007) SS 1 
+Respiratory rate, bpm (0043,1008) SS 1 
+Respiratory trigger point (0043,1009) SS 1 
+Type of receiver used (0043,100A) SS 1 
+Peak rate of change of gradient field (0043,100B) DS 1 
+Limits in units of percent (0043,100C) DS 1 
+PSD estimated limit (0043,100D) DS 1 
+PSD estimated limit in tesla per second (0043,100E) DS 1 
+Saravghead (0043,100F) DS 1 
+Window value (0043,1010) US 1 
+GE image integrity (0043,101C) SS 1 
+Level value (0043,101D) SS 1 
+Unique image iden (0043,1028) OB 1 
+Histogram tables (0043,1029) OB 1 
+User defined data (0043,102A) OB 1 
+Private Scan Options (0043,102B) SS 4 
+Effective echo spacing (0043,102C) SS 1 
+String slop field 1 (0043,102D) SH 1 
+String slop field 2 (0043,102E) SH 1 
+Image Type (real, imaginary, phase, magnitude) (0043,102F) SS 1 
+Vas collapse flag (0043,1030) SS 1 
+
+RA cord of target recon center (0043,1031) DS 2 
+Vas flags (0043,1032) SS 1 
+Neg_scanspacing (0043,1033) FL 1 
+Offset Frequency (0043,1034) IS 1 
+User_usage_tag (0043,1035) UL 1 
+User_fill_map_MSW (0043,1036) UL 1 
+User_fill_map_LSW (0043,1037) UL 1 
+User data 25...User data 48 (0043,1038) FL 24
+Slop_int_6... slop_int_9 (0043,1039) IS 4 
+ 6: b_value 
+ 7: private imaging options 2 
+ 8: ihtagging
+ 9: ihtagspc 
+Slop_int_10...slop_int_17 (0043,1060) IS 8
+ 10: ihfcineim 
+ 11: ihfcinent 
+ 12: Reserved
+ 13: oprtarr 
+ 14: averages
+ 15: Current Station #
+ 16: Total # of Stations
+ 17: Reserved 
+ 
+Scanner Study Entity UID (0043,1061) UI 1 
+Scanner Study ID (0043,1062) SH 1 
+Scanner Table Entry (single gradient coil systems only)
+Scanner Table Entry + Gradient Coil Selected (0043,106f) DS 3 or 4
+
+
+-------------------------------------------------
+Notes from:
+PathSpeedtm PACS Version 8.0 CONFORMANCE STATEMENT for DICOM V3.0
+http://www.gehealthcare.com/it_solutions/connectivity/pdf/iis_fp_10282r1.pdf
+ok -> www.gehealthcare.com/usen/interoperability/dicom/docs/iis_fp_10282r1.pdf
+
+See GE_ImageThumbnails
+--------------------------------------------------
+
+
+About ACUSON.dic, generated from aspen3.pdf:
+[Acusion Aspen(tm) Ultrasound System Dicom Conformance Statement for aspen 3.0 3.5]
+http://mais.baikal.ru/library/pdf/aspen3.pdf
+
+
+--------------------------------------------------
+According to :
+http://www.gehealthcare.com/usen/interoperability/dicom/docs/ep250409r4.pdf
+
+2.5 EXTENSIONS / SPECIALIZATIONS / PRIVATIZATIONS 
+If so configured, the product will send ultrasound raw data information in private data elements designated by the Private 
+Creator element: 
+
+Element Name Tag VR VM Description 
+Private Creator 7FE1,00xx LO 1 GEMS_Ultrasound_MovieGroup_001
+ 
+This means that all private tags starting with 7FE1,xx will belong to the GEMS_Ultrasound_MovieGroup_001. 
+If so configured, the product will send preview image in private data elements designated by the Private Creator element: 
+
+Element Name Tag VR VM Description 
+Private Creator 6003,00xx LO 1 GEMS_Ultrasound_ImageGroup_001
+ 
+This means that all private tags starting with 6003,00xx will belong to the GEMS_Ultrasound_ImageGroup_001
+
+--------------------------------------------------
+In preparation for the new Philips dictionaray with values taken from:
+http://www.medical.philips.com/main/company/connectivity/assets/docs/dicomcs/mr91.pdf
+rename the old dictionary to avoid confusion
+
+Basically all the dictionary should have been:
+
+2001 xx22 FL 1 Water Fat Shift
+instead of
+2001 1022 FL 1 Water Fat Shift
+
+
+About GEMS Genie:
+Doc was taken from:
+http://www.gehealthcare.com/usen/fun_img/nmedicine/nmdicom/docs/confstmt.pdf
+
+433  echo "http://www.gehealthcare.com/usen/fun_img/nmedicine/nmdicom/docs/confstmt.pdf" > GEMS-Genie.dic
+To build GEMS-Genie I also used: http://www.gehealthcare.com/usen/fun_img/nmedicine/nmdicom/docs/2383442_100r1.pdf
+
+434  echo "http://www.gehealthcare.com/usen/interoperability/dicom/docs/2270669_100r0_3.pdf" > GEMS-Advance.dic
+
+According to 2270669_100r0_3.pdf, there is different interpretation for:
+
+0009 10b3 SL 1 GE Advance ImageSet.ir_num_subsets
+0009 10b4 FL 1 GE Advance ImageSet.ir_recon_fov
+
+or:
+
+0009 10b4 FL 1 GE Advance ImageSet.ir_num_subsets
+... grrrr
+ok nevermind I found also this document:
+http://www.gehealthcare.com/usen/fun_img/pet/docs/5101600GDOr0.pdf
+that defines:
+0009 10b3 SL 1 GE Advance ImageSet.ir_num_subsets
+
+
+--------------------------------------------------
+About 6002,1000 I only found one ref:
+[Advantage Workstation 4.0 CONFORMANCE STATEMENT for DICOM V3.0]
+http://www.gehealthcare.com/usen/interoperability/dicom/docs/2261302_100r1.pdf
+
+
+--------------------------------------------------
+For GEMS-Advantx.dic
+[EchoPAC PC version 4 CONFORMANCE STATEMENT for DICOM]
+http://www.gehealthcare.com/it_solutions/connectivity/pdf/EP250409r06.pdf
+ok -> www.gehealthcare.com/usen/interoperability/dicom/docs/EP250409r06.pdf
+http://www.gehealthcare.com/usen/xr/dicom/docs/2142506_100r01_ps.pdf
+
+
+--------------------------------------------------
+ELSCINT Dictionary was done by ripping stuff from:
+Value Multiplicity was deducted by looking at the values for this particular image...
+http://www.merge-efilm.com/phpbb2/viewtopic.php?t=171&sid=11cde708c1f4feac179467c117373732
+
+
+About PHILIPS-EasyVision.dic, BE VERY AFRAID:
+http://www.medical.philips.com/main/company/connectivity/assets/docs/dicomcs/ev44_final.pdf
+... pure pleasure...
+
+
+--------------------------------------------------
+SPI.dic and SIEMENS.dic were generated based on D. Clunie work at:
+[3.3.2.2.2 Siemens Magnetom SP SPI Format]
+http://www.dclunie.com/medical-image-faq/html/part4.html
+
+and spi.tpl siemens.tpl from dicom3tools (20050611 snapshot)
+
+
+---------------------------------------------------
+
+Alright SIEMENS is totally screwed up...
+Let's have a look at:
+[Aristos VB10]
+http://www.medical.siemens.com/siemens/en_INT/rg_marcom_FBAs/files/brochures/DICOM/ax/Aristos_DicomConformanceStatement.pdf
+
+SOMATOM syngo VA50A DICOM Conformance Statement
+http://61.62.116.208/webhd/adams/LinkedDocuments/SENSATION_16.pdf
+
+SOMATOM syngo VA45A DICOM Conformance Statement
+http://61.62.116.208/webhd/adams/LinkedDocuments/EMOTION%206%20DICOM.pdf
+
+Somaris/5 VA70A CT DICOM Conformance Statement
+http://www.petscaninfo.com/zportal/portals/ctimi/prodandserv/dicom_statements/xvi.pdf
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/SIEMENS-syngo.dic b/Utilities/ITK/Utilities/gdcm/Dicts/SIEMENS-syngo.dic
new file mode 100644
index 0000000000000000000000000000000000000000..16a6de38e4de6eea5fc9cbda4e998174bbf9a60a
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/SIEMENS-syngo.dic
@@ -0,0 +1,96 @@
+See :
+
+www.tamsinfo.toshiba.com/docrequest/pdf/esoft3.5.pdf
+for more fields (page 106 ?!?)
+or
+www.medical.siemens.com/siemens/en_INT/rg_marcom_FBAs/files/brochures/DICOM/mr/MEDWS_DCS_ESK.pdf
+
+CSA Non Image
+-------------
+0029 xx08 CS 1 CSA Data Type
+0029 xx09 LO 1 CSA Data Version
+0029 xx10 OB 1 CSA Data Info
+7fe1 xx10 OB 1 CSA Data
+
+CSA Image Header Module
+-----------------------
+
+0029 xx08  CS 1 CSA  Image Header Type
+0029 xx09  LO 1 CSA  Image Header Version
+0029 xx10  OB 1 CSA  Image Header Info
+
+CSA Series Header Module
+-----------------------
+
+0029 xx08  CS 1 CSA  Series Header Type
+0029 xx09  LO 1 CSA  Series Header Version
+0029 xx10  OB 1 CSA  Series Header Info
+
+0029 xx08  CS 1 syngo Report Type
+0029 xx09  LO 1 syngo Report
+0029 xx15  US 1 SR Variant
+0029 xx17  US 1 SC SOP Instance UID
+
+0029 xx10  OB 1 syngo Report Data
+0029 xx11  OB 1 syngo Report Presentation
+
+MEDCOM Header Module
+--------------------
+
+0029 xx08 CS 1 Medcom Header Type
+0029 xx09 LO 1 Medcom Header Version
+0029 xx10 OB 1 Medcom Header Info
+0029 xx20 OB 1 Medcom History Information
+0029 xx31 LO 1 PMTF Information 1
+0029 xx32 UL 1 PMTF Information 2
+0029 xx33 UL 1 PMTF Information 3
+0029 xx34 CS 1 PMTF Information 4
+0029 xx35 UL 1 PMTF Information 5
+0029 xx40 SQ 1 Application Header Sequence
+0029 xx41 CS 1 Application Header Type
+0029 xx42 LO 1 Application Header ID
+0029 xx43 LO 1 Application Header Version
+0029 xx44 OB 1 Application Header Info
+0029 xx40 SQ 1 Application Header Sequence
+0029 xx50 LO 8 Workflow Control Flags
+0029 xx51 CS 1 Archive Management Flag Keep Online 
+0029 xx52 CS 1 Archive Management Flag Do Not Archive
+0029 xx53 CS 1 Image Location Status
+0029 xx54 DS 1 Estimated Retrieve Time
+0029 xx55 CS 1 Data Size of Retrieved Images 
+
+MEDCOM History Information
+-------------------------- 
+
+
+MEDCOM OOG Module
+-----------------
+0029 xx08 CS 1 MedCom OOG Type
+0029 xx09 LO 1 MedCom OOG Version
+0029 xx10 OB 1 MedCom OOG Info
+
+syngo Report Data
+-----------------
+
+Standard Extensions of NM SOP Class
+-----------------------------------
+0019 00a5 SS 1-n Number of repeats per phase 
+0019 00a6 SS 1-n Cycles per repeat
+0019 00a7 SL 1-n Repeat start time  
+0019 00a8 SL 1-n Repeat stop time  
+0019 00a9 SL 1-n Effective repeat time 
+0019 00aa SS 1-n Adquiered cycles per repeat
+0021 0000 OB 1 ECAT File Menu Header
+-->
+--> 0021 0000 is NOT a group length  ?!?
+-->
+0021 0001 OB 1 ECAT File SubHeader
+0033 0000 FL n Flood correction Matrix Det 1 upto SR 2.0
+0033 0001 FL n Flood correction Matrix Det 2 upto SR 2.0
+
+
+etc ...
+See :
+tamsinfo.toshiba.com/docrequest/pdf/esoft3.5.pdf
+for more fields (page 106 ?!?)
+
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/SIEMENS.dic b/Utilities/ITK/Utilities/gdcm/Dicts/SIEMENS.dic
new file mode 100644
index 0000000000000000000000000000000000000000..73575226f091f6eedd166649fe42da756ab7b09f
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/SIEMENS.dic
@@ -0,0 +1,217 @@
+0009 1010 CS 1 Storage Mode
+0009 1015 LO 1 UID
+0009 1040 SH 1 Data Object Subtype
+0009 1041 SH 1 Data Object Subtype
+
+0009 1110 LO 1 Recognition Code
+0009 1130 UL 1 Byte Offset of Original Header
+0009 1131 UL 1 Length of Original Header
+0009 1140 UL 1 Byte Offset of Pixelmatrix
+0009 1141 UL 1 Length of Pixelmatrix In Bytes
+
+0009 1310 LO 1 Generator Identification Label
+0009 1311 LO 1 Gantry Identification Label
+0009 1312 LO 1 X-Ray Tube Identification Label
+0009 1313 LO 1 Detector Identification Label
+0009 1314 LO 1 DAS Identification Label
+0009 1315 LO 1 SMI Identification Label
+0009 1316 LO 1 CPU Identification Label
+0009 1320 SH 1 Header Version
+
+0011 0000 UL 1 Group Length
+0011 0003 LO 1 Patient UID
+0011 0004 LO 1 Patient ID
+0011 000a LO 1 Case ID
+0011 0010 DA 1 Registration Date
+0011 0010 LO 1 Patient UID
+0011 0011 TM 1 Registration Time
+0011 0011 LO 1 Patient ID
+0011 0020 DA 1 Patient Registration Date
+0011 0021 TM 1 Patient Registration Time
+0011 0022 LO 1 Request ID
+0011 0023 DS 1 Used Patient Weight
+0011 0023 LO 1 Examination UID
+0011 0030 LO 1 Patientname RIS
+0011 0031 LO 1 Patientprename RIS
+0011 0040 IS 1 Organ Code
+0011 0040 LO 1 Patient Hospital Status
+0011 0041 LO 1 Medical Alerts
+0011 0042 LO 1 Contrast Allergies
+0011 00a1 DA 1 Patient Registration Date
+0011 00a2 TM 1 Patient Registration Time
+0011 00b0 LO 1 Patient Last Name
+0011 00b2 LO 1 Patient First Name
+0011 00b4 LO 1 Patient Hospital Status
+0011 00bc TM 1 Current Location Time
+0011 00c0 LO 1 Patient Insurance Status
+0011 00d0 LO 1 Patient Billing Type
+0011 00d2 LO 1 Patient Billing Address
+
+0013 0000 PN 1 Modifying Physician
+0013 0010 DA 1 Modification Date
+0013 0012 TM 1 Modification Time
+0013 0020 PN 1 Patient Name
+0013 0022 LO 1 Patient Id
+0013 0030 DA 1 Patient Birthdate
+0013 0031 DS 1 Patient Weight
+0013 0032 LO 1 Patients Maiden Name
+0013 0033 LO 1 Referring Physician
+0013 0034 LO 1 Admitting Diagnosis
+0013 0035 LO 1 Patient Sex
+0013 0040 LO 1 Procedure Description
+0013 0042 LO 1 Patient Rest Direction
+0013 0044 LO 1 Patient Position
+0013 0046 LO 1 View Direction
+
+0019 1010 IS 1 Net Frequency
+0019 1020 CS 1 Measurement Mode
+0019 1030 CS 1 Calculation Mode
+0019 1050 IS 1 Noise Level
+0019 1060 IS 1 Number of Data Bytes
+0019 1210 DS 1 Total Measurement Time Nominal
+0019 1211 DS 1 Total Measurement Time Current
+0019 1212 DS 1 Start Delay Time
+0019 1213 DS 1 Dwell Time
+0019 1214 IS 1 Number of Phases
+0019 1216 UL 2 Sequence Control Mask
+0019 1218 UL 1 Measurement Status Mask
+0019 1220 IS 1 Number of Fourier Lines Nominal
+0019 1221 IS 1 Number of Fourier Lines Current
+0019 1226 IS 1 Number of Fourier Lines after Zero
+0019 1228 IS 1 First Measured Fourier Line
+0019 1230 IS 1 Acquisition Columns
+0019 1231 IS 1 Reconstruction Columns
+0019 1240 IS 1 Array Coil Element Number
+0019 1241 UL 1 Array Coil Element Select Mask
+0019 1242 UL 1 Array Coil Element Data Mask
+0019 1243 IS 1-n Array Coil Element To ADC Connect
+0019 1244 DS 1-n Array Coil Element Noise Level
+0019 1245 IS 1 Array Coil ADC Pair Number
+0019 1246 UL 1 Array Coil Combination Mask
+0019 1250 IS 1 Number of Averages Current
+0019 1260 DS 1 Flip Angle
+0019 1270 IS 1 Number of Prescans
+0019 1281 CS 1 Filter Type for Raw Data
+0019 1282 DS 1-n Filter Parameter for Raw Data
+0019 1283 CS 1 Filter Type for Image Data
+0019 1284 DS 1-n Filter Parameter for Image Data
+0019 1285 CS 1 Filter Type for Phase Correction
+0019 1286 DS 1-n Filter Parameter for Phase Correction
+0019 1287 CS 1 Normalization Filter Type for Image Data
+0019 1288 DS 1-n Normalization Filter Parameter for Image Data
+0019 1290 IS 1 Number of Saturation Regions
+0019 1291 DS 6 Saturation Phase Encoding Vector Sagittal Component
+0019 1292 DS 6 Saturation Readout Vector Sagittal Component
+0019 1293 IS 1 EPI Stimulation Monitor Mode
+0019 1294 DS 1 Image Rotation Angle
+0019 1296 UL 3 Coil ID Mask
+0019 1297 UL 2 Coil Class Mask
+0019 1298 DS 3 Coil Position
+0019 12a0 DS 1 EPI Reconstruction Phase
+0019 12a1 DS 1 EPI Reconstruction Slope
+
+0019 1410 IS 1 Distance Source To Source Side Collimator
+0019 1411 IS 1 Distance Source To Detector Side Collimator
+0019 1412 DS 1 Magnetic Field Strength
+0019 1414 DS 1 ADC Voltage
+0019 1416 DS 2 ADC Offset
+0019 1420 DS 1 Transmitter Amplitude
+0019 1420 IS 1 Number of Possible Channels
+0019 1421 IS 1 Mean Channel Number
+0019 1421 IS 1 Number of Transmitter Amplitudes
+0019 1422 DS 1 Detector Spacing
+0019 1422 DS 1 Transmitter Attenuator
+0019 1423 DS 1 Detector Center
+0019 1424 DS 1 Reading Integration Time
+0019 1424 DS 1 Transmitter Calibration
+0019 1426 DS 1 Transmitter Reference
+0019 1450 DS 1 Detector Alignment
+0019 1450 DS 1 Receiver Total Gain
+0019 1451 DS 1 Receiver Amplifier Gain
+0019 1452 DS 1 Receiver Preamplifier Gain
+0019 1454 DS 1 Receiver Cable Attenuation
+0019 1455 DS 1 Receiver Reference Gain
+0019 1456 DS 1 Receiver Filter Frequency
+0019 1460 DS 1 Focus Alignment
+0019 1460 DS 1 Reconstruction Scale Factor
+0019 1462 DS 1 Reference Scale Factor
+0019 1465 UL 1 Focal Spot Deflection Amplitude
+0019 1466 UL 1 Focal Spot Deflection Phase
+0019 1467 UL 1 Focal Spot Deflection Offset
+0019 1470 DS 1 Water Scaling Factor
+0019 1470 DS 1 Phase Gradient Amplitude
+0019 1471 DS 1 Interpolation Factor
+0019 1471 DS 1 Readout Gradient Amplitude
+0019 1472 DS 1 Selection Gradient Amplitude
+0019 1480 DS 3 Gradient Delay Time
+0019 1480 CS 1 Patient Region
+0019 1482 DS 1 Total Gradient Delay Time
+0019 1482 CS 1 Patient Phase of Life
+0019 1490 DS 1 Osteo Offset
+0019 1490 LO 1 Sensitivity Correction Label
+0019 1491 DS 6 Saturation Phase Encoding Vector Coronal Component
+0019 1492 DS 6 Saturation Readout Vector Coronal Component
+0019 1492 DS 1 Osteo Regression Line Slope
+0019 1493 DS 1 Osteo Regression Line Intercept
+0019 1494 IS 1 Osteo Standardization Code
+0019 1496 IS 1 Osteo Phantom Number
+0019 14a0 IS 1 RF Watchdog Mask
+0019 14a1 DS 1 EPI Reconstruction Slope
+0019 14a2 DS 1 RF Power Error Indicator
+0019 14a5 DS 3 Specific Absorption Rate Whole Body
+0019 14a6 DS 3 Specific Energy Dose
+0019 14b0 DS 1 Feed per Rotation
+0019 14b0 UL 1 Adjustment Status Mask
+0019 14bd IS 1 Pulmo Trigger Level
+0019 14be DS 1 Expiratoric Reserve Volume
+0019 14bf DS 1 Vital Capacity
+0019 14c0 DS 1 Pulmo Water
+0019 14c1 DS 1 Pulmo Air
+0019 14c1 DS 6 EPI Capacity
+0019 14c2 DS 3 EPI Inductance
+0019 14c2 DA 1 PulmoDate
+0019 14c3 IS 1-n EPI Switch Configuration Code
+0019 14c3 TM 1 PulmoTime
+0019 14c4 IS 1-n EPI Switch Hardware Code
+0019 14c5 DS 1-n EPI Switch Delay Time
+0019 14d1 DS 1 Flow Sensitivity
+0019 14d2 CS 1 Calculation Submode
+0019 14d3 DS 1 Field of View Ratio
+0019 14d4 IS 1 Base Raw Matrix Size
+0019 14d5 IS 1 2D Oversampling Lines
+0019 14d6 IS 1 3D Phase Oversampling Partitions
+0019 14d7 IS 1 Echo Line Position
+0019 14d8 IS 1 Echo Column Position
+0019 14d9 IS 1 Lines Per Segment
+0019 14da CS 1 Phase Coding Direction
+0019 1456 DS 1 Receiver Filter Frequency
+
+0029 1110 CS 1 Window Style
+0029 1120 CS 3 Pixel Quality Code
+0029 1122 IS 3 Pixel Quality Value
+0029 1150 CS 1 Archive Code
+0029 1151 CS 1 Exposure Code
+0029 1152 IS 1 Sort Code
+0029 1160 LO 1 Splash
+
+0029 1108 CS 1 MedCom Header Type
+0029 1109 LO 1 MedCom Header Version
+0029 1110 OB 1 MedCom Header Info
+0029 1120 OB 1 MedCom History Information
+0029 1131 LO 1 PMTF Information 1
+0029 1132 UL 1 PMTF Information 2
+0029 1133 UL 1 PMTF Information 3
+0029 1134 CS 1 PMTF Information 4
+0029 1135 UL 1 PMTF Information 5
+0029 1140 SQ 1 Application Header Sequence
+0029 1141 CS 1 Application Header Type
+0029 1142 LO 1 Application Header ID
+0029 1143 LO 1 Application Header Version
+0029 1144 OB 1 Application Header Info
+0029 1150 LO 8 Workflow Control Flags
+0029 1151 CS 1 Archive Management Flag Keep Online
+0029 1152 CS 1 Archive Management Flag Do Not Archive
+0029 1153 CS 1 Image Location Status
+0029 1154 DS 1 Estimated Retrieve Time
+0029 1155 DS 1 Data Size of Retrieved Images
+
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/SPI.dic b/Utilities/ITK/Utilities/gdcm/Dicts/SPI.dic
new file mode 100644
index 0000000000000000000000000000000000000000..0cd8be9735ee289f7c08af73614dc070bdb1dccf
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/SPI.dic
@@ -0,0 +1,8 @@
+0009 0010 LO 1 Comments
+0009 0015 LO 1 UID
+0009 0040 US 1 Data Object Type
+0009 0041 SH 1 Data Object Subtype
+0011 0010 LO 1 Organ
+0011 0015 LO 1 Allergy Indication
+0011 0020 LO 1 Pregnancy
+0029 0060 LO 1 Compression Algorithm
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/dicomAttributeTypes.dic b/Utilities/ITK/Utilities/gdcm/Dicts/dicomAttributeTypes.dic
new file mode 100644
index 0000000000000000000000000000000000000000..fe5cd5bcbfc939bc1914dd31a0a94aa6914aaf48
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/dicomAttributeTypes.dic
@@ -0,0 +1,46 @@
+Found in :
+ http://medical.nema.org/dicom/2004/04_15PU.PDF
+
+Unused till now :-( 
+ 
+
+1.2.840.10008.15.0.3.1            dicomDeviceName
+1.2.840.10008.15.0.3.2            dicomDescription
+1.2.840.10008.15.0.3.3            dicomManufacturer
+1.2.840.10008.15.0.3.4            dicomManufacturerModelName
+1.2.840.10008.15.0.3.5            dicomSoftwareVersion
+1.2.840.10008.15.0.3.6            dicomVendorData
+1.2.840.10008.15.0.3.7            dicomAETitle
+1.2.840.10008.15.0.3.8            dicomNetworkConnectionReference
+1.2.840.10008.15.0.3.9            dicomApplicationCluster
+1.2.840.10008.15.0.3.10           dicomAssociationInitiator
+1.2.840.10008.15.0.3.11           dicomAssociationAcceptor
+1.2.840.10008.15.0.3.12           dicomHostname
+1.2.840.10008.15.0.3.13           dicomPort
+1.2.840.10008.15.0.3.14           dicomSOPClass
+1.2.840.10008.15.0.3.15           dicomTransferRole
+1.2.840.10008.15.0.3.16           dicomTransferSyntax
+1.2.840.10008.15.0.3.17           dicomPrimaryDeviceType
+1.2.840.10008.15.0.3.18           dicomRelatedDeviceReference
+1.2.840.10008.15.0.3.19           dicomPreferredCalledAETitle
+1.2.840.10008.15.0.3.20           dicomTLSCyphersuite
+1.2.840.10008.15.0.3.21           dicomAuthorizedNodeCertificateReference
+1.2.840.10008.15.0.3.22           dicomThisNodeCertificateReference
+1.2.840.10008.15.0.3.23           dicomInstalled
+1.2.840.10008.15.0.3.24           dicomStationName
+1.2.840.10008.15.0.3.25           dicomDeviceSerialNumber
+1.2.840.10008.15.0.3.26           dicomInstitutionName
+1.2.840.10008.15.0.3.27           dicomInstitutionAddress
+1.2.840.10008.15.0.3.28           dicomInstitutionDepartmentName
+1.2.840.10008.15.0.3.29           dicomIssuerOfPatientID
+1.2.840.10008.15.0.3.30           dicomPreferredCallingAETitle
+1.2.840.10008.15.0.3.31           dicomSupportedCharacterSet
+1.2.840.10008.15.0.4.1            dicomConfigurationRoot
+1.2.840.10008.15.0.4.2            dicomDevicesRoot
+1.2.840.10008.15.0.4.3            dicomUniqueAETitlesRegistryRoot
+1.2.840.10008.15.0.4.4            dicomDevice
+1.2.840.10008.15.0.4.5            dicomNetworkAE
+1.2.840.10008.15.0.4.6            dicomNetworkConnection
+1.2.840.10008.15.0.4.7            dicomUniqueAETitle
+1.2.840.10008.15.0.4.8            dicomTransferCapability
+
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/dicomGroupNameAbbreviations.dic b/Utilities/ITK/Utilities/gdcm/Dicts/dicomGroupNameAbbreviations.dic
new file mode 100644
index 0000000000000000000000000000000000000000..a56d3203f827e63a661c6a0261946ef41d525582
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/dicomGroupNameAbbreviations.dic
@@ -0,0 +1,63 @@
+// Group Number  
+// NHI Abbreviation (when known) - not part of DICOM standard -
+// Meaning          (when known) - not part of DICOM standard -
+
+0000 CMD Command
+0002 META Meta Elements
+0004 DIR Directory
+0008 ID Identification Informations
+0010 PAT Patient Informations
+0012 CLI Clinical Trial Informations
+0018 ACQ Acquisition Informations
+0020 REL Relationship Informations
+0022 ??? ???
+0028 IMG Image Informations
+0032 SDY Study Informations
+0038 VIS Visit Information
+003a WAV Waveform Information
+0040 PRC Procedure Informations
+0050 DEV Device Informations
+0054 NMI Nuclear Medicine
+0060 HIS Histogram
+0070 ??? ???
+0088 MED Medicine
+0100 ??? ???
+0400 ??? ???
+2000 BFS ???
+2010 BFB ???
+2020 BIB ???
+2030 BAB ???
+2040 IOB ???
+2050 ??? ???
+2100 PJ ???
+2110 PRINTER Printer
+2130 ??? ???
+2200 ??? ???
+3002 RT Radiotherapy
+3004 DVH ???
+3006 SSET ???
+3008 ??? ???
+300a RT Radiotherapy
+300c RT Radiotherapy
+300e RT Radiotherapy
+4008 RES Results
+4ffe ??? ???
+5000 CRV Curve
+5002 CRV Curve
+5004 CRV Curve
+5006 CRV Curve
+5008 CRV Curve
+500a CRV Curve
+500c CRV Curve
+500e CRV Curve
+5200 ??? ???
+5400 ??? ???
+5600 ??? ???
+6000 OLY Overlays
+6002 OLY Overlays
+6004 OLY Overlays
+6008 OLY Overlays
+600a OLY Overlays
+600c OLY Overlays
+600e OLY Overlays
+7fe0 PXL Pixels
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/dicomTS.dic b/Utilities/ITK/Utilities/gdcm/Dicts/dicomTS.dic
new file mode 100644
index 0000000000000000000000000000000000000000..bff4b6331b5b83e32e8905643fc9e71df5a8db13
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/dicomTS.dic
@@ -0,0 +1,205 @@
+1.2.840.10008.1.2        Implicit VR - Little Endian
+1.2.840.10008.1.2.1      Explicit VR - Little Endian
+1.2.840.10008.1.2.1.99   Deflated Explicit VR - Little Endian
+1.2.840.10008.1.2.2      Explicit VR - Big Endian
+1.2.840.10008.1.2.4.50   JPEG Baseline (Process 1)
+1.2.840.10008.1.2.4.51   JPEG Extended (Process 2 & 4)
+1.2.840.10008.1.2.4.52   JPEG Extended (Process 3 & 5) (Retired)
+1.2.840.10008.1.2.4.53   JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8) (Retired)
+1.2.840.10008.1.2.4.54   JPEG Spectral Selection, Non-Hierarchical (Process 7 & 9) (Retired)
+1.2.840.10008.1.2.4.55   JPEG Full Progression, Non-Hierarchical (Process 10 & 12) (Retired)
+1.2.840.10008.1.2.4.56   JPEG Full Progression, Non-Hierarchical (Process 11 & 13) (Retired)
+1.2.840.10008.1.2.4.57   JPEG Lossless Non-Hierarchical (Process 14)
+1.2.840.10008.1.2.4.58   JPEG Lossless Non-Hierarchical (Process 15) (Retired)
+1.2.840.10008.1.2.4.59   JPEG Extended Hierarchical (Process 16 & 18) (Retired)
+1.2.840.10008.1.2.4.60   JPEG Spectral Selection, Non-Hierarchical (Process 17 & 19) (Retired)
+1.2.840.10008.1.2.4.61   JPEG Spectral Selection, Hierarchical (Process 20 & 22) (Retired)
+1.2.840.10008.1.2.4.62   JPEG Spectral Selection, Hierarchical (Process 21 & 23) (Retired)
+1.2.840.10008.1.2.4.63   JPEG Full Progression, Hierarchical (Process 24 & 26) (Retired)
+1.2.840.10008.1.2.4.64   JPEG Full Progression, Hierarchical (Process 25 & 27) (Retired)
+1.2.840.10008.1.2.4.65   JPEG Lossless, Hierarchical (Process 28) (Retired)
+1.2.840.10008.1.2.4.66   JPEG Lossless, Hierarchical (Process 29) (Retired))
+1.2.840.10008.1.2.4.70   JPEG Lossless, Non-Hierarchical, First-Order Prediction (Process 14 [Selection Value 1])
+1.2.840.10008.1.2.4.80   JPEG-LS Lossless Image Compression
+1.2.840.10008.1.2.4.81   JPEG-LS Lossy (Near-Lossless) Image Compression
+1.2.840.10008.1.2.4.90   JPEG 2000 Image Compression (Lossless Only)
+1.2.840.10008.1.2.4.91   JPEG 2000 Image Compression
+1.2.840.10008.1.2.4.100  MPEG2 Main Profile @ Main Level
+1.2.840.10008.1.2.5      RLE Lossless
+1.2.840.113619.5.2       Implicit VR - Big Endian (G.E Private)
+
+1.2.840.10008.1.3.10              Media Storage Directory Storage
+1.2.840.10008.1.4.1.1             Talairach Brain Atlas Frame of Reference
+1.2.840.10008.1.4.1.2             SPM2 T1 Frame of Reference
+1.2.840.10008.1.4.1.3             SPM2 T2 Frame of Reference
+1.2.840.10008.1.4.1.4             SPM2 PD Frame of Reference
+1.2.840.10008.1.4.1.5             SPM2 EPI Frame of Reference
+1.2.840.10008.1.4.1.6             SPM2 FIL T1 Frame of Reference
+1.2.840.10008.1.4.1.7             SPM2 PET Frame of Reference
+1.2.840.10008.1.4.1.8             SPM2 TRANSM Frame of Reference
+1.2.840.10008.1.4.1.9             SPM2 SPECT Frame of Reference
+1.2.840.10008.1.4.1.10            SPM2 GRAY Frame of Reference
+1.2.840.10008.1.4.1.11            SPM2 WHITE Frame of Reference
+1.2.840.10008.1.4.1.12            SPM2 CSF Frame of Reference
+1.2.840.10008.1.4.1.13            SPM2 BRAINMASK Frame of Reference
+1.2.840.10008.1.4.1.14            SPM2 AVG305T1 Frame of Reference
+1.2.840.10008.1.4.1.15            SPM2 AVG152T1 Frame of Reference
+1.2.840.10008.1.4.1.16            SPM2 AVG152T2 Frame of Reference
+1.2.840.10008.1.4.1.17            SPM2 AVG152PD Frame of Reference
+1.2.840.10008.1.4.1.18            SPM2 SINGLESUBJT1 Frame of Reference
+1.2.840.10008.1.4.2.1             ICBM 452 T1 Frame of Reference
+1.2.840.10008.1.4.2.2             ICBM Single Subject MRI Frame of Reference
+
+1.2.840.10008.1.1                 Verification SOP Class
+1.2.840.10008.1.9                 Basic Study Content Notification SOP Class
+1.2.840.10008.1.20.1              Image Commitment Push Model SOP Class
+1.2.840.10008.1.20.1.1            Image Commitment Push Model SOP Instance
+1.2.840.10008.1.20.2              Image Commitment Push Model SOP Class (Retired)
+1.2.840.10008.1.20.2.1            Image Commitment Push Model SOP Instance (Retired)
+
+1.2.840.10008.1.40                Procedural Event Logging SOP Class
+1.2.840.10008.1.40.1              Procedural Event Logging SOP Instance
+1.2.840.10008.2.16.4              DICOM Controlled Terminology
+1.2.840.10008.3.1.1.1             DICOM Application Context Name
+1.2.840.10008.3.1.2.1.1           Detached Patient Management SOP Class
+1.2.840.10008.3.1.2.1.4           Detached Patient Management Meta SOP Class
+1.2.840.10008.3.1.2.2.1           Detached Visit Management SOP Class
+1.2.840.10008.3.1.2.3.1           Detached Study Management SOP Class
+1.2.840.10008.3.1.2.3.2           Study Component Management SOP Class
+1.2.840.10008.3.1.2.3.3           Modality Performed Procedure Step SOP Class
+1.2.840.10008.3.1.2.3.4           Modality Performed Procedure Step Retrieve SOP Class
+1.2.840.10008.3.1.2.3.5           Modality Performed Procedure Step Notification SOP Class
+1.2.840.10008.3.1.2.5.1           Detached Results Management SOP Class
+1.2.840.10008.3.1.2.5.4           Detached Results Management Meta SOP Class
+1.2.840.10008.3.1.2.5.5           Detached Study Management Meta SOP Class
+1.2.840.10008.3.1.2.6.1           Detached Interpretation Management SOP Class
+
+1.2.840.10008.4.2                 Storage Device Class
+
+1.2.840.10008.5.1.1.1             Basic Film Session SOP Class
+1.2.840.10008.5.1.1.2             Basic Film Box SOP Class
+1.2.840.10008.5.1.1.4             Basic Gray Scale Image Box SOP Class
+1.2.840.10008.5.1.1.4.1           Basic Color Image Box SOP Class
+1.2.840.10008.5.1.1.4.2           Referenced Image Box SOP Class (Retired)
+1.2.840.10008.5.1.1.9             Basic Gray Scale Print Management Meta SOP Class
+1.2.840.10008.5.1.1.9.1           Referenced Gray Scale Print Management Meta SOP Class(Retired)
+1.2.840.10008.5.1.1.14            Print Job SOP Class
+1.2.840.10008.5.1.1.15            Basic Annotation Box SOP Class
+1.2.840.10008.5.1.1.16            Printer SOP Class
+1.2.840.10008.5.1.1.16.376        Printer Configuration Retrieval SOP Class
+1.2.840.10008.5.1.1.17            Printer SOP Instance
+1.2.840.10008.5.1.1.17.376        Printer Configuration Retrieval SOP Instance
+1.2.840.10008.5.1.1.18            Basic Color Print Management Meta SOP Class
+1.2.840.10008.5.1.1.18.1          Referenced Color Print Management Meta SOP Class (Retired)
+1.2.840.10008.5.1.1.22            VOI LUT Box SOP Class
+1.2.840.10008.5.1.1.23            Presentation LUT Box SOP Class
+1.2.840.10008.5.1.1.24            Image Overlay Box SOP Class (Retired)
+1.2.840.10008.5.1.1.24.1          Basic Print Image Overlay Box SOP Class
+1.2.840.10008.5.1.1.25            Print Queue SOP Instance
+1.2.840.10008.5.1.1.26            Print Queue Management SOP Class
+1.2.840.10008.5.1.1.27            Stored Print Storage SOP Class
+1.2.840.10008.5.1.1.29            Hardcopy Grayscale Image Storage SOP Class
+1.2.840.10008.5.1.1.30            Hardcopy Color Image Storage SOP Class
+1.2.840.10008.5.1.1.31            Pull Print Request SOP Class
+1.2.840.10008.5.1.1.32            Pull Stored Print Management Meta SOP Class
+1.2.840.10008.5.1.1.33            Media Creation Management SOP Class UID
+
+1.2.840.10008.5.1.4.1.1.1         Computed Radiography Image Storage
+1.2.840.10008.5.1.4.1.1.1.1       Digital X-Ray Image Storage - For Presentation
+1.2.840.10008.5.1.4.1.1.1.1.1     Digital X-Ray Image Storage - For Processing
+1.2.840.10008.5.1.4.1.1.1.2       Digital Mammography Image Storage - For Presentation
+1.2.840.10008.5.1.4.1.1.1.2.1     Digital Mammography Image Storage - For Processing
+1.2.840.10008.5.1.4.1.1.1.3       Digital Intra-oral X-ray Image Storage - For Presentation
+1.2.840.10008.5.1.4.1.1.1.3.1     Digital Intra-oral X-Ray Image Storage - For Processing
+1.2.840.10008.5.1.4.1.1.2         CT Image Storage
+1.2.840.10008.5.1.4.1.1.2.1       Enhanced CT Image Storage
+
+1.2.840.10008.5.1.4.1.1.3         Ultrasound Multi-Frame Image Storage (Retired)
+1.2.840.10008.5.1.4.1.1.3.1       Ultrasound Multi-Frame Image Storage
+1.2.840.10008.5.1.4.1.1.4         MR Image Storage
+1.2.840.10008.5.1.4.1.1.4.1       Enhanced MR Image Storage
+1.2.840.10008.5.1.4.1.1.4.2       MR Spectroscopy Storage
+1.2.840.10008.5.1.4.1.1.5         Nuclear Medicine Image Storage (Retired)
+1.2.840.10008.5.1.4.1.1.6         Ultrasound Image Storage (Retired)
+1.2.840.10008.5.1.4.1.1.6.1       Ultrasound Image Storage
+1.2.840.10008.5.1.4.1.1.7         Secondary Capture Image Storage
+1.2.840.10008.5.1.4.1.1.7.1       Multi-frame Single Bit Secondary Capture Image Storage
+1.2.840.10008.5.1.4.1.1.7.2       Multi-frame Grayscale Byte Secondary Capture Image Storage
+1.2.840.10008.5.1.4.1.1.7.3       Multi-frame Grayscale Word Secondary Capture Image Storage
+1.2.840.10008.5.1.4.1.1.7.4       Multi-frame True Color Secondary Capture Image Storage
+1.2.840.10008.5.1.4.1.1.8         Standalone Overlay Storage
+1.2.840.10008.5.1.4.1.1.9         Standalone Curve Storage
+1.2.840.10008.5.1.4.1.1.9.1.1     12-Lead ECG Waveform Storage
+1.2.840.10008.5.1.4.1.1.9.1.2     General ECG Waveform Storage
+1.2.840.10008.5.1.4.1.1.9.1.3     Ambulatory ECG Waveform Storage
+1.2.840.10008.5.1.4.1.1.9.2.1     Hemodynamic Waveform Storage
+1.2.840.10008.5.1.4.1.1.9.3.1     Cardiac Electrophysiology Waveform Storage
+1.2.840.10008.5.1.4.1.1.9.4.1     Basic Voice Audio Waveform Storage
+1.2.840.10008.5.1.4.1.1.10        Standalone Modality LUT Storage
+1.2.840.10008.5.1.4.1.1.11        Standalone VOI LUT Storage
+1.2.840.10008.5.1.4.1.1.11.1      Grayscale Softcopy Presentation State Storage SOP Class
+1.2.840.10008.5.1.4.1.1.12.1      X-Ray Angiographic Image Storage
+1.2.840.10008.5.1.4.1.1.12.2      X-Ray Radiofluoroscoping Image Storage
+1.2.840.10008.5.1.4.1.1.12.3      X-Ray Angiographic Bi-Plane Image Storage (Retired)
+1.2.840.10008.5.1.4.1.1.20        Nuclear Medicine Image Storage
+1.2.840.10008.5.1.4.1.1.66        Raw Data Storage
+1.2.840.10008.5.1.4.1.1.66.1      Spacial Registration Storage
+1.2.840.10008.5.1.4.1.1.66.2      Spacial Fiducials Storage
+
+1.2.840.10008.5.1.4.1.1.77.1      VL Image Storage (Retired)
+1.2.840.10008.5.1.4.1.1.77.2      VL MultiFrame Image Storage (Retired)
+1.2.840.10008.5.1.4.1.1.77.1.1    VL Endoscoping Image Storage
+1.2.840.10008.5.1.4.1.1.77.1.1.1  Video Endoscoping Image Storage
+1.2.840.10008.5.1.4.1.1.77.1.2    VL Microscoping Image Storage
+1.2.840.10008.5.1.4.1.1.77.1.2.1  Video Microscoping Image Storage
+1.2.840.10008.5.1.4.1.1.77.1.3    VL Slide-Coordinates Microscoping Image Storage
+1.2.840.10008.5.1.4.1.1.77.1.4    VL Photographic Image Storage
+1.2.840.10008.5.1.4.1.1.77.1.4.1  Video Photographic Image Storage
+1.2.840.10008.5.1.4.1.1.77.1.5.1  Ophthalmic Photography 8 Bit Image Storage
+1.2.840.10008.5.1.4.1.1.77.1.5.2  Ophthalmic Photography 16 Bit Image Storage
+1.2.840.10008.5.1.4.1.1.77.1.5.3  Stereometric Relationship Storage
+
+1.2.840.10008.5.1.4.1.1.88.1      SR Text Storage
+1.2.840.10008.5.1.4.1.1.88.2      SR Audio Storage
+1.2.840.10008.5.1.4.1.1.88.3      SR Detail Storage
+1.2.840.10008.5.1.4.1.1.88.4      SR Comprehensive Storage
+1.2.840.10008.5.1.4.1.1.88.11     Basic Text SR
+1.2.840.10008.5.1.4.1.1.88.22     Enhanced SR
+1.2.840.10008.5.1.4.1.1.88.33     Comprehensive SR
+1.2.840.10008.5.1.4.1.1.88.40     Procedure Log Storage
+1.2.840.10008.5.1.4.1.1.88.50     Mammography CAD SR
+1.2.840.10008.5.1.4.1.1.88.59     Key Object Selection Document
+1.2.840.10008.5.1.4.1.1.88.65     Chest CAD SR
+1.2.840.10008.5.1.4.1.1.104.1     Encapsulated PDF Storage
+1.2.840.10008.5.1.4.1.1.128       Positron Emission Tomography Image Storage
+1.2.840.10008.5.1.4.1.1.129       Standalone PET Curve Storage
+1.2.840.10008.5.1.4.1.1.481.1     RT Image Storage
+1.2.840.10008.5.1.4.1.1.481.2     RT Dose Storage
+1.2.840.10008.5.1.4.1.1.481.3     RT Structure Set Storage
+1.2.840.10008.5.1.4.1.1.481.4     RT Beams Treatment Record Storage
+1.2.840.10008.5.1.4.1.1.481.5     RT Plan Storage
+1.2.840.10008.5.1.4.1.1.481.6     RT Brachy Treatment Record Storage
+1.2.840.10008.5.1.4.1.1.481.7     RT Treatment Summary Record Storage
+
+1.2.840.10008.5.1.4.1.2.1.1       Patient Root Query/Retrieve Information Model - FIND
+1.2.840.10008.5.1.4.1.2.1.2       Patient Root Query/Retrieve Information Model - MOVE
+1.2.840.10008.5.1.4.1.2.1.3       Patient Root Query/Retrieve Information Model - GET
+1.2.840.10008.5.1.4.1.2.2.1       Study Root Query/Retrieve Information Model - FIND
+1.2.840.10008.5.1.4.1.2.2.2       Study Root Query/Retrieve Information Model - MOVE
+1.2.840.10008.5.1.4.1.2.2.3       Study Root Query/Retrieve Information Model - GET
+1.2.840.10008.5.1.4.1.2.3.1       Patient/Study Only Query/Retrieve Information Model - FIND
+1.2.840.10008.5.1.4.1.2.3.2       Patient/Study Only Query/Retrieve Information Model - GET
+1.2.840.10008.5.1.4.1.2.3.3       Patient/Study Only Query/Retrieve Information Model - MOVE
+1.2.840.10008.5.1.4.31            Modality Worklist Information Model - FIND
+1.2.840.10008.5.1.4.32.1          General Purpose Worklist Information Model - FIND
+1.2.840.10008.5.1.4.32.2          General Purpose Scheduled Procedure Step SOP Class
+1.2.840.10008.5.1.4.32.3          General Purpose Performed Procedure Step SOP Class
+1.2.840.10008.5.1.4.32            General Purpose Worklist Management Meta SOP Class
+1.2.840.10008.5.1.4.33            Instance Availability Notification SOP Class
+1.2.840.10008.5.1.4.37.1          General Relevant Patient Information Query
+1.2.840.10008.5.1.4.37.2          Breast Imaging Relevant Patient Information Query
+1.2.840.10008.5.1.4.37.3          Cardiac Relevant Patient Information Query
+
+1.2.840.113619.5.2                Implicit VR Big Endian DLX (G.E Private)
+1.3.12.2.1107.5.9.1               CSA Non-Image Storage
+1.3.46.670589.2.5.1.1             3D Subpage Storage
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/dicomV3.dic b/Utilities/ITK/Utilities/gdcm/Dicts/dicomV3.dic
new file mode 100644
index 0000000000000000000000000000000000000000..eb61dbff3f62af3e37ff95632121d542357fb773
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/dicomV3.dic
@@ -0,0 +1,2560 @@
+0000 0000 UL 1 Group Length
+0000 0001 UL 1 Command Length to End (RET)
+0000 0002 UI 1 Affected SOP Class UID
+0000 0003 UI 1 Requested SOP Class UID
+0000 0010 SH 1 Command Recognition Code (RET)
+0000 0100 US 1 Command Field
+0000 0110 US 1 Message ID (first)
+0000 0120 US 1 Message ID Responded to
+0000 0600 AE 1 Move Destination
+0000 0700 US 1 Priority
+0000 0800 US 1 Data Set Type
+0000 0900 US 1 Status
+0000 0901 AT 1 Offending Element
+0000 0902 LO 1 Error Comment
+0000 0903 US 1 Error ID
+0000 1001 UI 1 SOP Requested Instance UID
+0000 1000 UI 1 SOP Affected Instance UID
+0000 1002 US 1 Event Type ID
+0000 1008 US 1 Action Type ID
+0000 1020 US 1 Remaining Suboperations
+0000 1021 US 1 Completed Suboperations
+0000 1022 US 1 Failed Suboperations
+0000 1023 US 1 Warning Suboperations
+0000 1030 AE 1 AE Title
+0000 1031 US 1 Message ID (second)
+0000 1005 AT 1 Attribute Identifier List
+
+0002 0000 UL 1 Group Length
+0002 0001 OB 1 File Meta Information Version
+0002 0002 UI 1 Media Storage SOP Class UID
+0002 0003 UI 1 Media Storage SOP Instance UID
+0002 0010 UI 1 Transfer Syntax UID
+0002 0012 UI 1 Implementation Class UID
+0002 0013 SH 1 Implementation Version Name
+0002 0016 AE 1 Source Application Entity Title
+0002 0100 UI 1 Private Information Creator UID
+0002 0102 OB 1 Private Information
+
+0004 0000 UL 1 Group Length
+0004 1130 CS 1 File-set ID
+0004 1141 CS 1-8 File-set Descriptor File ID
+0004 1142 CS 1 Specific Character Set of File-set Descriptor File
+0004 1200 UL 1 Offset of the First Directory Record of the Root Directory Entity
+0004 1202 UL 1 Offset of the Last Directory Record of the Root Directory Entity
+0004 1212 US 1 File-set Consistency Flag
+0004 1220 SQ 1 Directory Record Sequence
+0004 1400 UL 1 Offset of the Next Directory Record
+0004 1410 US 1 Record In-use Flag
+0004 1420 UL 1 Offset of Referenced Lower-Level Directory Entity
+0004 1430 CS 1 Directory Record Type
+0004 1432 UI 1 Private Record UID
+0004 1500 CS 1-8 Referenced File ID
+0004 1504 UL 1 MRDR Directory Record Offset
+0004 1510 UI 1 Referenced SOP Class UID in File
+0004 1511 UI 1 Referenced SOP Instance UID in File
+0004 1512 UI 1 Referenced Transfer Syntax UID in File
+0004 151a UI 1-n Referenced Related General SOP Class UID in File
+0004 1600 UL 1 Number of References
+
+0008 0000 UL 1 Group Length
+0008 0001 UL 1 Length to End (RET)
+0008 0005 CS 1-n Specific Character Set
+0008 0008 CS 1-n Image Type
+0008 0010 LO 1 Recognition Code (RET)
+0008 0012 DA 1 Instance Creation Date
+0008 0013 TM 1 Instance Creation Time
+0008 0014 UI 1 Instance Creator UID
+0008 0016 UI 1 SOP Class UID
+0008 0018 UI 1 SOP Instance UID
+0008 001a UI 1-n Related General SOP Class UID
+0008 001b UI 1 Original Specialized SOP Class UID
+0008 0020 DA 1 Study Date
+0008 0021 DA 1 Series Date
+0008 0022 DA 1 Acquisition Date
+0008 0023 DA 1 Content Date
+0008 0024 DA 1 Overlay Date
+0008 0025 DA 1 Curve Date
+0008 002a DT 1 Acquisition Datetime
+0008 0030 TM 1 Study Time
+0008 0031 TM 1 Series Time
+0008 0032 TM 1 Acquisition Time
+0008 0033 TM 1 Content Time
+0008 0034 TM 1 Overlay Time
+0008 0035 TM 1 Curve Time
+0008 0040 SS 1 Data Set Type (RET)
+0008 0041 LO 1 Data Set Subtype (RET)
+0008 0042 CS 1 Nuclear Medicine Series Type (RET)
+0008 0050 SH 1 Accession Number
+0008 0052 CS 1 Query/Retrieve Level
+0008 0054 AE 1-n Retrieve AE Title
+0008 0056 CS 1 Instance Availability
+0008 0058 UI 1-n Failed SOP Instance UID List
+0008 0060 CS 1 Modality
+0008 0061 CS 1-n Modalities in Study
+0008 0062 UI 1-n SOP Classes in Study
+0008 0064 CS 1 Conversion Type
+0008 0068 CS 1 Presentation Intent Type
+0008 0070 LO 1 Manufacturer
+0008 0080 LO 1 Institution Name
+0008 0081 ST 1 Institution Address
+0008 0082 SQ 1 Institution Code Sequence
+0008 0090 PN 1 Referring Physician's Name
+0008 0092 ST 1 Referring Physician's Address
+0008 0094 SH 1-n Referring Physician's Telephone Numbers
+0008 0096 SQ 1 Referring Physician Identification Sequence
+0008 0100 SH 1 Code Value
+0008 0102 SH 1 Coding Scheme Designator
+0008 0103 SH 1 Coding Scheme Version
+0008 0104 LO 1 Code Meaning
+0008 0105 CS 1 Mapping Resource
+0008 0106 DT 1 Context Group Version
+0008 0107 DT 1 Context Group Local Version
+0008 010b CS 1 Context Group Extension Flag
+0008 010c UI 1 Coding Scheme UID
+0008 010d UI 1 Context Group Extension Creator UID
+0008 010f CS 1 Context Identifier
+0008 0110 SQ 1 Coding Scheme Identification Sequence
+0008 0112 LO 1 Coding Scheme Registry
+0008 0114 ST 1 Coding Scheme External ID
+0008 0115 ST 1 Coding Scheme Name
+0008 0116 ST 1 Responsible Organization
+0008 0201 SH 1 Timezone Offset From UTC
+0008 1000 LT 1 Network ID (RET)
+0008 1010 SH 1 Station Name
+0008 1030 LO 1 Study Description
+0008 1032 SQ 1 Procedure Code Sequence
+0008 103e LO 1 Series Description
+0008 1040 LO 1 Institutional Department Name
+0008 1048 PN 1-n Physician(s) of Record
+0008 1049 SQ 1 Physician(s) of Record Identification Sequence
+0008 1050 PN 1-n Performing Physician's Name
+0008 1052 SQ 1 Performing Physician Identification Sequence
+0008 1060 PN 1-n Name of Physician(s) Reading Study
+0008 1062 SQ 1 Physician(s) Reading Study Identification Sequence
+0008 1070 PN 1-n Operator's Name
+0008 1072 SQ 1 Operator Identification Sequence
+0008 1080 LO 1-n Admitting Diagnoses Description
+0008 1084 SQ 1 Admitting Diagnoses Code Sequence
+0008 1090 LO 1 Manufacturer's Model Name
+0008 1100 SQ 1 Referenced Results Sequence
+0008 1110 SQ 1 Referenced Study Sequence
+0008 1111 SQ 1 Referenced Performed Procedure Step Sequence
+0008 1115 SQ 1 Referenced Series Sequence
+0008 1120 SQ 1 Referenced Patient Sequence
+0008 1125 SQ 1 Referenced Visit Sequence
+0008 1130 SQ 1 Referenced Overlay Sequence
+0008 113a SQ 1 Referenced Waveform Sequence
+0008 1140 SQ 1 Referenced Image Sequence
+0008 1145 SQ 1 Referenced Curve Sequence
+0008 114a SQ 1 Referenced Instance Sequence
+0008 1150 UI 1 Referenced SOP Class UID
+0008 1155 UI 1 Referenced SOP Instance UID
+0008 115a UI 1-n SOP Classes Supported
+0008 1160 IS 1-n Referenced Frame Number
+0008 1195 UI 1 Transaction UID
+0008 1197 US 1 Failure Reason
+0008 1198 SQ 1 Failed SOP Sequence
+0008 1199 SQ 1 Referenced SOP Sequence
+0008 1200 SQ 1 Studies Containing Other Referenced Instances Sequence
+0008 1250 SQ 1 Related Series Sequence
+0008 2110 CS 1 Lossy Image Compression (RET)
+0008 2111 ST 1 Derivation Description
+0008 2112 SQ 1 Source Image Sequence
+0008 2120 SH 1 Stage Name
+0008 2122 IS 1 Stage Number
+0008 2124 IS 1 Number of Stages
+0008 2127 SH 1 View Name
+0008 2128 IS 1 View Number
+0008 2129 IS 1 Number of Event Timers
+0008 212a IS 1 Number of Views in Stage
+0008 2130 DS 1-n Event Elapsed Time(s)
+0008 2132 LO 1-n Event Timer Name(s)
+0008 2142 IS 1 Start Trim
+0008 2143 IS 1 Stop Trim
+0008 2144 IS 1 Recommended Display Frame Rate
+0008 2200 CS 1 Transducer Position (RET)
+0008 2204 CS 1 Transducer Orientation (RET)
+0008 2208 CS 1 Anatomic Structure (RET)
+0008 2218 SQ 1 Anatomic Region Sequence
+0008 2220 SQ 1 Anatomic Region Modifier Sequence
+0008 2228 SQ 1 Primary Anatomic Structure Sequence
+0008 2229 SQ 1 Anatomic Structure, Space or Region Sequence
+0008 2230 SQ 1 Primary Anatomic Structure Modifier Sequence
+0008 2240 SQ 1 Transducer Position Sequence
+0008 2242 SQ 1 Transducer Position Modifier Sequence
+0008 2244 SQ 1 Transducer Orientation Sequence
+0008 2246 SQ 1 Transducer Orientation Modifier Sequence
+0008 3001 SQ 1 Alternate Representation Sequence
+0008 4000 LT 1-n Identifying Comments (RET)
+0008 9007 CS 4 Frame Type
+0008 9092 SQ 1 Referenced Image Evidence Sequence
+0008 9121 SQ 1 Referenced Raw Data Sequence
+0008 9123 UI 1 Creator-Version UID
+0008 9124 SQ 1 Derivation Image Sequence
+0008 9154 SQ 1 Source Image Evidence Sequence
+0008 9205 CS 1 Pixel Presentation
+0008 9206 CS 1 Volumetric Properties
+0008 9207 CS 1 Volume Based Calculation Technique
+0008 9208 CS 1 Complex Image Component
+0008 9209 CS 1 Acquisition Contrast
+0008 9215 SQ 1 Derivation Code Sequence
+0008 9237 SQ 1 Referenced Grayscale Presentation State Sequence
+
+0010 0000 UL 1 Group Length
+0010 0010 PN 1 Patient's Name
+0010 0020 LO 1 Patient ID
+0010 0021 LO 1 Issuer of Patient ID
+0010 0030 DA 1 Patient's Birth Date
+0010 0032 TM 1 Patient's Birth Time
+0010 0040 CS 1 Patient's Sex
+0010 0050 SQ 1 Patient's Insurance Plan Code Sequence
+0010 0101 SQ 1 Patient's Primary Language Code Sequence
+0010 0102 SQ 1 Patient's Primary Language Code Modifier Sequence
+0010 1000 LO 1-n Other Patient IDs
+0010 1001 PN 1-n Other Patient Names
+0010 1005 PN 1 Patient's Birth Name
+0010 1010 AS 1 Patient's Age
+0010 1020 DS 1 Patient's Size
+0010 1030 DS 1 Patient's Weight
+0010 1040 LO 1 Patient's Address
+0010 1050 LT 1-n Insurance Plan Identification (RET)
+0010 1060 PN 1 Patient's Mother's Birth Name
+0010 1080 LO 1 Military Rank
+0010 1081 LO 1 Branch of Service
+0010 1090 LO 1 Medical Record Locator
+0010 2000 LO 1-n Medical Alerts
+0010 2110 LO 1-n Contrast Allergies
+0010 2150 LO 1 Country of Residence
+0010 2152 LO 1 Region of Residence
+0010 2154 SH 1-n Patient's Telephone Numbers
+0010 2160 SH 1 Ethnic Group
+0010 2180 SH 1 Occupation
+0010 21a0 CS 1 Smoking Status
+0010 21b0 LT 1 Additional Patient History
+0010 21c0 US 1 Pregnancy Status
+0010 21d0 DA 1 Last Menstrual Date
+0010 21f0 LO 1 Patient's Religious Preference
+0010 4000 LT 1 Patient Comments
+
+0012 0010 LO 1 Clinical Trial Sponsor Name
+0012 0020 LO 1 Clinical Trial Protocol ID
+0012 0021 LO 1 Clinical Trial Protocol Name
+0012 0030 LO 1 Clinical Trial Site ID
+0012 0031 LO 1 Clinical Trial Site Name
+0012 0040 LO 1 Clinical Trial Subject ID
+0012 0042 LO 1 Clinical Trial Subject Reading ID
+0012 0050 LO 1 Clinical Trial Time Point ID
+0012 0051 ST 1 Clinical Trial Time Point Description
+0012 0060 LO 1 Clinical Trial Coordinating Center Name
+
+0018 0000 UL 1 Group Length
+0018 0010 LO 1 Contrast/Bolus Agent
+0018 0012 SQ 1 Contrast/Bolus Agent Sequence
+0018 0014 SQ 1 Contrast/Bolus Administration Route Sequence
+0018 0015 CS 1 Body Part Examined
+0018 0020 CS 1-n Scanning Sequence
+0018 0021 CS 1-n Sequence Variant
+0018 0022 CS 1-n Scan Options
+0018 0023 CS 1 MR Acquisition Type
+0018 0024 SH 1 Sequence Name
+0018 0025 CS 1 Angio Flag
+0018 0026 SQ 1 Intervention Drug Information Sequence
+0018 0027 TM 1 Intervention Drug Stop Time
+0018 0028 DS 1 Intervention Drug Dose
+0018 0029 SQ 1 Intervention Drug Sequence
+0018 002a SQ 1 Additional Drug Sequence
+0018 0030 LO 1-n Radionuclide (RET)
+0018 0031 LO 1 Radiopharmaceutical
+0018 0032 DS 1 Energy Window Centerline (RET)
+0018 0033 DS 1-n Energy Window Total Width (RET)
+0018 0034 LO 1 Intervention Drug Name
+0018 0035 TM 1 Intervention Drug Start Time
+0018 0036 SQ 1 Intervention Sequence
+0018 0037 CS 1 Therapy Type (RET)
+0018 0038 CS 1 Intervention Status
+0018 0039 CS 1 Therapy Description (RET)
+0018 003a ST 1 Intervention Description
+0018 0040 IS 1 Cine Rate
+0018 0050 DS 1 Slice Thickness
+0018 0060 DS 1 KVP
+0018 0070 IS 1 Counts Accumulated
+0018 0071 CS 1 Acquisition Termination Condition
+0018 0072 DS 1 Effective Duration
+0018 0073 CS 1 Acquisition Start Condition
+0018 0074 IS 1 Acquisition Start Condition Data
+0018 0075 IS 1 Acquisition Termination Condition Data
+0018 0080 DS 1 Repetition Time
+0018 0081 DS 1 Echo Time
+0018 0082 DS 1 Inversion Time
+0018 0083 DS 1 Number of Averages
+0018 0084 DS 1 Imaging Frequency
+0018 0085 SH 1 Imaged Nucleus
+0018 0086 IS 1-n Echo Number(s)
+0018 0087 DS 1 Magnetic Field Strength
+0018 0088 DS 1 Spacing Between Slices
+0018 0089 IS 1 Number of Phase Encoding Steps
+0018 0090 DS 1 Data Collection Diameter
+0018 0091 IS 1 Echo Train Length
+0018 0093 DS 1 Percent Sampling
+0018 0094 DS 1 Percent Phase Field of View
+0018 0095 DS 1 Pixel Bandwidth
+0018 1000 LO 1 Device Serial Number
+0018 1004 LO 1 Plate ID
+0018 1010 LO 1 Secondary Capture Device ID
+0018 1011 LO 1 Hardcopy Creation Device ID
+0018 1012 DA 1 Date of Secondary Capture
+0018 1014 TM 1 Time of Secondary Capture
+0018 1016 LO 1 Secondary Capture Device Manufacturer
+0018 1017 LO 1 Hardcopy Device Manufacturer
+0018 1018 LO 1 Secondary Capture Device Manufacturer's Model Name
+0018 1019 LO 1-n Secondary Capture Device Software Version(s)
+0018 101a LO 1-n Hardcopy Device Software Version
+0018 101b LO 1 Hardcopy Device Manufacturer's Model Name
+0018 1020 LO 1-n Software Version(s)
+0018 1022 SH 1 Video Image Format Acquired
+0018 1023 LO 1 Digital Image Format Acquired
+0018 1030 LO 1 Protocol Name
+0018 1040 LO 1 Contrast/Bolus Route
+0018 1041 DS 1 Contrast/Bolus Volume
+0018 1042 TM 1 Contrast/Bolus Start Time
+0018 1043 TM 1 Contrast/Bolus Stop Time
+0018 1044 DS 1 Contrast/Bolus Total Dose
+0018 1045 IS 1 Syringe Counts
+0018 1046 DS 1-n Contrast Flow Rate
+0018 1047 DS 1-n Contrast Flow Duration
+0018 1048 CS 1 Contrast/Bolus Ingredient
+0018 1049 DS 1 Contrast/Bolus Ingredient Concentration
+0018 1050 DS 1 Spatial Resolution
+0018 1060 DS 1 Trigger Time
+0018 1061 LO 1 Trigger Source or Type
+0018 1062 IS 1 Nominal Interval
+0018 1063 DS 1 Frame Time
+0018 1064 LO 1 Framing Type
+0018 1065 DS 1-n Frame Time Vector
+0018 1066 DS 1 Frame Delay
+0018 1067 DS 1 Image Trigger Delay
+0018 1068 DS 1 Multiplex Group Time Offset
+0018 1069 DS 1 Trigger Time Offset
+0018 106a CS 1 Synchronization Trigger
+0018 106c US 2 Synchronization Channel
+0018 106e UL 1 Trigger Sample Position
+0018 1070 LO 1 Radiopharmaceutical Route
+0018 1071 DS 1 Radiopharmaceutical Volume
+0018 1072 TM 1 Radiopharmaceutical Start Time
+0018 1073 TM 1 Radiopharmaceutical Stop Time
+0018 1074 DS 1 Radionuclide Total Dose
+0018 1075 DS 1 Radionuclide Half Life
+0018 1076 DS 1 Radionuclide Positron Fraction
+0018 1077 DS 1 Radiopharmaceutical Specific Activity
+0018 1080 CS 1 Beat Rejection Flag
+0018 1081 IS 1 Low R-R Value
+0018 1082 IS 1 High R-R Value
+0018 1083 IS 1 Intervals Acquired
+0018 1084 IS 1 Intervals Rejected
+0018 1085 LO 1 PVC Rejection
+0018 1086 IS 1 Skip Beats
+0018 1088 IS 1 Heart Rate
+0018 1090 IS 1 Cardiac Number of Images
+0018 1094 IS 1 Trigger Window
+0018 1100 DS 1 Reconstruction Diameter
+0018 1110 DS 1 Distance Source to Detector
+0018 1111 DS 1 Distance Source to Patient
+0018 1114 DS 1 Estimated Radiographic Magnification Factor
+0018 1120 DS 1 Gantry/Detector Tilt
+0018 1121 DS 1 Gantry/Detector Slew
+0018 1130 DS 1 Table Height
+0018 1131 DS 1 Table Traverse
+0018 1134 CS 1 Table Motion
+0018 1135 DS 1-n Table Vertical Increment
+0018 1136 DS 1-n Table Lateral Increment
+0018 1137 DS 1-n Table Longitudinal Increment
+0018 1138 DS 1 Table Angle
+0018 113a CS 1 Table Type
+0018 1140 CS 1 Rotation Direction
+0018 1141 DS 1 Angular Position
+0018 1142 DS 1-n Radial Position
+0018 1143 DS 1 Scan Arc
+0018 1144 DS 1 Angular Step
+0018 1145 DS 1 Center of Rotation Offset
+0018 1146 DS 1-n Rotation Offset (RET)
+0018 1147 CS 1 Field of View Shape
+0018 1149 IS 1-2 Field of View Dimension(s)
+0018 1150 IS 1 Exposure Time
+0018 1151 IS 1 X-ray Tube Current
+0018 1152 IS 1 Exposure
+0018 1153 IS 1 Exposure in uAs
+0018 1154 DS 1 Average Pulse Width
+0018 1155 CS 1 Radiation Setting
+0018 1156 CS 1 Rectification Type
+0018 115a CS 1 Radiation Mode
+0018 115e DS 1 Image Area Dose Product
+0018 1160 SH 1 Filter Type
+0018 1161 LO 1-n Type of Filters
+0018 1162 DS 1 Intensifier Size
+0018 1164 DS 2 Imager Pixel Spacing
+0018 1166 CS 1-n Grid
+0018 1170 IS 1 Generator Power
+0018 1180 SH 1 Collimator/grid Name
+0018 1181 CS 1 Collimator Type
+0018 1182 IS 1-2 Focal Distance
+0018 1183 DS 1-2 X Focus Center
+0018 1184 DS 1-2 Y Focus Center
+0018 1190 DS 1-n Focal Spot(s)
+0018 1191 CS 1 Anode Target Material
+0018 11a0 DS 1 Body Part Thickness
+0018 11a2 DS 1 Compression Force
+0018 1200 DA 1-n Date of Last Calibration
+0018 1201 TM 1-n Time of Last Calibration
+0018 1210 SH 1-n Convolution Kernel
+0018 1240 IS 1-n Upper/Lower Pixel Values (RET)
+0018 1242 IS 1 Actual Frame Duration
+0018 1243 IS 1 Count Rate
+0018 1244 US 1 Preferred Playback Sequencing
+0018 1250 SH 1 Receive Coil Name
+0018 1251 SH 1 Transmit Coil Name
+0018 1260 SH 1 Plate Type
+0018 1261 LO 1 Phosphor Type
+0018 1300 DS 1 Scan Velocity
+0018 1301 CS 1-n Whole Body Technique
+0018 1302 IS 1 Scan Length
+0018 1310 US 4 Acquisition Matrix
+0018 1312 CS 1 In-plane Phase Encoding Direction
+0018 1314 DS 1 Flip Angle
+0018 1315 CS 1 Variable Flip Angle Flag
+0018 1316 DS 1 SAR
+0018 1318 DS 1 dB/dt
+0018 1400 LO 1 Acquisition Device Processing Description
+0018 1401 LO 1 Acquisition Device Processing Code
+0018 1402 CS 1 Cassette Orientation
+0018 1403 CS 1 Cassette Size
+0018 1404 US 1 Exposures on Plate
+0018 1405 IS 1 Relative X-ray Exposure
+0018 1450 DS 1 Column Angulation
+0018 1460 DS 1 Tomo Layer Height
+0018 1470 DS 1 Tomo Angle
+0018 1480 DS 1 Tomo Time
+0018 1490 CS 1 Tomo Type
+0018 1491 CS 1 Tomo Class
+0018 1495 IS 1 Number of Tomosynthesis Source Images
+0018 1500 CS 1 Positioner Motion
+0018 1508 CS 1 Positioner Type
+0018 1510 DS 1 Positioner Primary Angle
+0018 1511 DS 1 Positioner Secondary Angle
+0018 1520 DS 1-n Positioner Primary Angle Increment
+0018 1521 DS 1-n Positioner Secondary Angle Increment
+0018 1530 DS 1 Detector Primary Angle
+0018 1531 DS 1 Detector Secondary Angle
+0018 1600 CS 1-3 Shutter Shape
+0018 1602 IS 1 Shutter Left Vertical Edge
+0018 1604 IS 1 Shutter Right Vertical Edge
+0018 1606 IS 1 Shutter Upper Horizontal Edge
+0018 1608 IS 1 Shutter Lower Horizontal Edge
+0018 1610 IS 2 Center of Circular Shutter
+0018 1612 IS 1 Radius of Circular Shutter
+0018 1620 IS 2-2n Vertices of the Polygonal Shutter
+0018 1622 US 1 Shutter Presentation Value
+0018 1623 US 1 Shutter Overlay Group
+0018 1700 CS 1-3 Collimator Shape
+0018 1702 IS 1 Collimator Left Vertical Edge
+0018 1704 IS 1 Collimator Right Vertical Edge
+0018 1706 IS 1 Collimator Upper Horizontal Edge
+0018 1708 IS 1 Collimator Lower Horizontal Edge
+0018 1710 IS 2 Center of Circular Collimator
+0018 1712 IS 1 Radius of Circular Collimator
+0018 1720 IS 2-2n Vertices of the Polygonal Collimator
+0018 1800 CS 1 Acquisition Time Synchronized
+0018 1801 SH 1 Time Source
+0018 1802 CS 1 Time Distribution Protocol
+0018 1803 LO 1 NTP Source Address
+0018 2001 IS 1-n Page Number Vector
+0018 2002 SH 1-n Frame Label Vector
+0018 2003 DS 1-n Frame Primary Angle Vector
+0018 2004 DS 1-n Frame Secondary Angle Vector
+0018 2005 DS 1-n Slice Location Vector
+0018 2006 SH 1-n Display Window Label Vector
+0018 2010 DS 2 Nominal Scanned Pixel Spacing
+0018 2020 CS 1 Digitizing Device Transport Direction
+0018 2030 DS 1 Rotation of Scanned Film
+0018 3100 CS 1 IVUS Acquisition
+0018 3101 DS 1 IVUS Pullback Rate
+0018 3102 DS 1 IVUS Gated Rate
+0018 3103 IS 1 IVUS Pullback Start Frame Number
+0018 3104 IS 1 IVUS Pullback Stop Frame Number
+0018 3105 IS 1-n Lesion Number
+0018 4000 LO 1-n Acquisition Comments (RET)
+0018 5000 SH 1-n Output Power
+0018 5010 LO 3 Transducer Data
+0018 5012 DS 1 Focus Depth
+0018 5020 LO 1 Processing Function
+0018 5021 LO 1 Postprocessing Function
+0018 5022 DS 1 Mechanical Index
+0018 5024 DS 1 Bone Thermal Index
+0018 5026 DS 1 Cranial Thermal Index
+0018 5027 DS 1 Soft Tissue Thermal Index
+0018 5028 DS 1 Soft Tissue-focus Thermal Index
+0018 5029 DS 1 Soft Tissue-surface Thermal Index
+0018 5030 DS 1 Dynamic Range (RET)
+0018 5040 DS 1 Total Gain (RET)
+0018 5050 IS 1 Depth of Scan Field
+0018 5100 CS 1 Patient Position
+0018 5101 CS 1 View Position
+0018 5104 SQ 1 Projection Eponymous Name Code Sequence
+0018 5210 DS 6 Image Transformation Matrix (RET)
+0018 5212 DS 3 Image Translation Vector (RET)
+0018 6000 DS 1 Sensitivity
+0018 6011 SQ 1 Sequence of Ultrasound Regions
+0018 6012 US 1 Region Spatial Format
+0018 6014 US 1 Region Data Type
+0018 6016 UL 1 Region Flags
+0018 6018 UL 1 Region Location Min X0
+0018 601a UL 1 Region Location Min Y0
+0018 601c UL 1 Region Location Max X1
+0018 601e UL 1 Region Location Max Y1
+0018 6020 SL 1 Reference Pixel X0
+0018 6022 SL 1 Reference Pixel Y0
+0018 6024 US 1 Physical Units X Direction
+0018 6026 US 1 Physical Units Y Direction
+0018 6028 FD 1 Reference Pixel Physical Value X
+0018 602a FD 1 Reference Pixel Physical Value Y
+0018 602c FD 1 Physical Delta X
+0018 602e FD 1 Physical Delta Y
+0018 6030 UL 1 Transducer Frequency
+0018 6031 CS 1 Transducer Type
+0018 6032 UL 1 Pulse Repetition Frequency
+0018 6034 FD 1 Doppler Correction Angle
+0018 6036 FD 1 Steering Angle
+0018 6038 UL 1 Doppler Sample Volume X Position (RET)
+0018 6039 SL 1 Doppler Sample Volume X Position
+0018 603a UL 1 Doppler Sample Volume Y Position (RET)
+0018 603b SL 1 Doppler Sample Volume Y Position
+0018 603c UL 1 TM-Line Position X0 (RET)
+0018 603d SL 1 TM-Line Position X0
+0018 603e UL 1 TM-Line Position Y0 (RET)
+0018 603f SL 1 TM-Line Position Y0
+0018 6040 UL 1 TM-Line Position X1 (RET)
+0018 6041 SL 1 TM-Line Position X1
+0018 6042 UL 1 TM-Line Position Y1 (RET)
+0018 6043 SL 1 TM-Line Position Y1
+0018 6044 US 1 Pixel Component Organization
+0018 6046 UL 1 Pixel Component Mask
+0018 6048 UL 1 Pixel Component Range Start
+0018 604a UL 1 Pixel Component Range Stop
+0018 604c US 1 Pixel Component Physical Units
+0018 604e US 1 Pixel Component Data Type
+0018 6050 UL 1 Number of Table Break Points
+0018 6052 UL 1-n Table of X Break Points
+0018 6054 FD 1-n Table of Y Break Points
+0018 6056 UL 1 Number of Table Entries
+0018 6058 UL 1-n Table of Pixel Values
+0018 605a FL 1-n Table of Parameter Values
+0018 6060 FL 1-n R Wave Time Vector
+0018 7000 CS 1 Detector Conditions Nominal Flag
+0018 7001 DS 1 Detector Temperature
+0018 7004 CS 1 Detector Type
+0018 7005 CS 1 Detector Configuration
+0018 7006 LT 1 Detector Description
+0018 7008 LT 1 Detector Mode
+0018 700a SH 1 Detector ID
+0018 700c DA 1 Date of Last Detector Calibration
+0018 700e TM 1 Time of Last Detector Calibration
+0018 7010 IS 1 Exposures on Detector Since Last Calibration
+0018 7011 IS 1 Exposures on Detector Since Manufactured
+0018 7012 DS 1 Detector Time Since Last Exposure
+0018 7014 DS 1 Detector Active Time
+0018 7016 DS 1 Detector Activation Offset From Exposure
+0018 701a DS 2 Detector Binning
+0018 7020 DS 2 Detector Element Physical Size
+0018 7022 DS 2 Detector Element Spacing
+0018 7024 CS 1 Detector Active Shape
+0018 7026 DS 1-2 Detector Active Dimension(s)
+0018 7028 DS 2 Detector Active Origin
+0018 702a LO 1 Detector Manufacturer Name
+0018 702b LO 1 Detector Manufacturer's Model Name
+0018 7030 DS 2 Field of View Origin
+0018 7032 DS 1 Field of View Rotation
+0018 7034 CS 1 Field of View Horizontal Flip
+0018 7040 LT 1 Grid Absorbing Material
+0018 7041 LT 1 Grid Spacing Material
+0018 7042 DS 1 Grid Thickness
+0018 7044 DS 1 Grid Pitch
+0018 7046 IS 2 Grid Aspect Ratio
+0018 7048 DS 1 Grid Period
+0018 704c DS 1 Grid Focal Distance
+0018 7050 CS 1-n Filter Material
+0018 7052 DS 1-n Filter Thickness Minimum
+0018 7054 DS 1-n Filter Thickness Maximum
+0018 7060 CS 1 Exposure Control Mode
+0018 7062 LT 1 Exposure Control Mode Description
+0018 7064 CS 1 Exposure Status
+0018 7065 DS 1 Phototimer Setting
+0018 8150 DS 1 Exposure Time in �S
+0018 8151 DS 1 X-Ray Tube Current in �A
+0018 9004 CS 1 Content Qualification
+0018 9005 SH 1 Pulse Sequence Name
+0018 9006 SQ 1 MR Imaging Modifier Sequence
+0018 9008 CS 1 Echo Pulse Sequence
+0018 9009 CS 1 Inversion Recovery
+0018 9010 CS 1 Flow Compensation
+0018 9011 CS 1 Multiple Spin Echo
+0018 9012 CS 1 Multi-planar Excitation
+0018 9014 CS 1 Phase Contrast
+0018 9015 CS 1 Time of Flight Contrast
+0018 9016 CS 1 Spoiling
+0018 9017 CS 1 Steady State Pulse Sequence
+0018 9018 CS 1 Echo Planar Pulse Sequence
+0018 9019 FD 1 Tag Angle First Axis
+0018 9020 CS 1 Magnetization Transfer
+0018 9021 CS 1 T2 Preparation
+0018 9022 CS 1 Blood Signal Nulling
+0018 9024 CS 1 Saturation Recovery
+0018 9025 CS 1 Spectrally Selected Suppression
+0018 9026 CS 1 Spectrally Selected Excitation
+0018 9027 CS 1 Spatial Pre-saturation
+0018 9028 CS 1 Tagging
+0018 9029 CS 1 Oversampling Phase
+0018 9030 FD 1 Tag Spacing First Dimension
+0018 9032 CS 1 Geometry of k-Space Traversal
+0018 9033 CS 1 Segmented k-Space Traversal
+0018 9034 CS 1 Rectilinear Phase Encode Reordering
+0018 9035 FD 1 Tag Thickness
+0018 9036 CS 1 Partial Fourier Direction
+0018 9037 CS 1 Cardiac Synchronization Technique
+0018 9041 LO 1 Receive Coil Manufacturer Name
+0018 9042 SQ 1 MR Receive Coil Sequence
+0018 9043 CS 1 Receive Coil Type
+0018 9044 CS 1 Quadrature Receive Coil
+0018 9045 SQ 1 Multi-Coil Definition Sequence
+0018 9046 LO 1 Multi-Coil Configuration
+0018 9047 SH 1 Multi-Coil Element Name
+0018 9048 CS 1 Multi-Coil Element Used
+0018 9049 SQ 1 MR Transmit Coil Sequence
+0018 9050 LO 1 Transmit Coil Manufacturer Name
+0018 9051 CS 1 Transmit Coil Type
+0018 9052 FD 1-2 Spectral Width
+0018 9053 FD 1-2 Chemical Shift Reference
+0018 9054 CS 1 Volume Localization Technique
+0018 9058 US 1 MR Acquisition Frequency Encoding Steps
+0018 9059 CS 1 De-coupling
+0018 9060 CS 1-2 De-coupled Nucleus
+0018 9061 FD 1-2 De-coupling Frequency
+0018 9062 CS 1 De-coupling Method
+0018 9063 FD 1-2 De-coupling Chemical Shift Reference
+0018 9064 CS 1 k-space Filtering
+0018 9065 CS 1-2 Time Domain Filtering
+0018 9066 US 1-2 Number of Zero fills
+0018 9067 CS 1 Baseline Correction
+0018 9069 FD 1 Parallel Reduction Factor In-plane
+0018 9070 FD 1 Cardiac R-R Interval Specified
+0018 9073 FD 1 Acquisition Duration
+0018 9074 DT 1 Frame Acquisition Datetime
+0018 9075 CS 1 Diffusion Directionality
+0018 9076 SQ 1 Diffusion Gradient Direction Sequence
+0018 9077 CS 1 Parallel Acquisition
+0018 9078 CS 1 Parallel Acquisition Technique
+0018 9079 FD 1-n Inversion Times
+0018 9080 ST 1 Metabolite Map Description
+0018 9081 CS 1 Partial Fourier
+0018 9082 FD 1 Effective Echo Time
+0018 9083 SQ 1 Metabolite Map Code Sequence
+0018 9084 SQ 1 Chemical Shift Sequence
+0018 9085 CS 1 Cardiac Signal Source
+0018 9087 FD 1 Diffusion b-value
+0018 9089 FD 3 Diffusion Gradient Orientation
+0018 9090 FD 3 Velocity Encoding Direction
+0018 9091 FD 1 Velocity Encoding Minimum Value
+0018 9093 US 1 Number of k-Space Trajectories
+0018 9094 CS 1 Coverage of k-Space
+0018 9095 UL 1 Spectroscopy Acquisition Phase Rows
+0018 9098 FD 1-2 Transmitter Frequency
+0018 9100 CS 1-2 Resonant Nucleus
+0018 9101 CS 1 Frequency Correction
+0018 9103 SQ 1 MR Spectroscopy FOV/Geometry Sequence
+0018 9104 FD 1 Slab Thickness
+0018 9105 FD 3 Slab Orientation
+0018 9106 FD 3 Mid Slab Position
+0018 9107 SQ 1 MR Spatial Saturation Sequence
+0018 9112 SQ 1 MR Timing and Related Parameters Sequence
+0018 9114 SQ 1 MR Echo Sequence
+0018 9115 SQ 1 MR Modifier Sequence
+0018 9117 SQ 1 MR Diffusion Sequence
+0018 9118 SQ 1 Cardiac Trigger Sequence
+0018 9119 SQ 1 MR Averages Sequence
+0018 9125 SQ 1 MR FOV/Geometry Sequence
+0018 9126 SQ 1 Volume Localization Sequence
+0018 9127 UL 1 Spectroscopy Acquisition Data Columns
+0018 9147 CS 1 Diffusion Anisotropy Type
+0018 9151 DT 1 Frame Reference Datetime
+0018 9152 SQ 1 MR Metabolite Map Sequence
+0018 9155 FD 1 Parallel Reduction Factor out-of-plane
+0018 9159 UL 1 Spectroscopy Acquisition Out-of-plane Phase Steps
+0018 9166 CS 1 Bulk Motion Status
+0018 9168 FD 1 Parallel Reduction Factor Second In-plane
+0018 9169 CS 1 Cardiac Beat Rejection Technique
+0018 9170 CS 1 Respiratory Motion Compensation Technique
+0018 9171 CS 1 Respiratory Signal Source
+0018 9172 CS 1 Bulk Motion Compensation Technique
+0018 9173 CS 1 Bulk Motion Signal Source
+0018 9174 CS 1 Applicable Safety Standard Agency
+0018 9175 LO 1 Applicable Safety Standard Description
+0018 9176 SQ 1 Operating Mode Sequence
+0018 9177 CS 1 Operating Mode Type
+0018 9178 CS 1 Operating Mode
+0018 9179 CS 1 Specific Absorption Rate Definition
+0018 9180 CS 1 Gradient Output Type
+0018 9181 FD 1 Specific Absorption Rate Value
+0018 9182 FD 1 Gradient Output
+0018 9183 CS 1 Flow Compensation Direction
+0018 9184 FD 1 Tagging Delay
+0018 9195 FD 1 Chemical Shifts Minimum Integration Limit in Hz (RET)
+0018 9196 FD 1 Chemical Shifts Maximum Integration Limit in Hz (RET)
+0018 9197 SQ 1 MR Velocity Encoding Sequence
+0018 9198 CS 1 First Order Phase Correction
+0018 9199 CS 1 Water Referenced Phase Correction
+0018 9200 CS 1 MR Spectroscopy Acquisition Type
+0018 9214 CS 1 Respiratory Cycle Position
+0018 9217 FD 1 Velocity Encoding Maximum Value
+0018 9218 FD 1 Tag Spacing Second Dimension
+0018 9219 SS 1 Tag Angle Second Axis
+0018 9220 FD 1 Frame Acquisition Duration
+0018 9226 SQ 1 MR Image Frame Type Sequence
+0018 9227 SQ 1 MR Spectroscopy Frame Type Sequence
+0018 9231 US 1 MR Acquisition Phase Encoding Steps in-plane
+0018 9232 US 1 MR Acquisition Phase Encoding Steps out-of-plane
+0018 9234 UL 1 Spectroscopy Acquisition Phase Columns
+0018 9236 CS 1 Cardiac Cycle Position
+0018 9239 SQ 1 Specific Absorption Rate Sequence
+0018 9295 FD 1 Chemical Shifts Minimum Integration Limit in ppm
+0018 9296 FD 1 Chemical Shifts Maximum Integration Limit in ppm
+0018 9240 US 1 RF Echo Train Length
+0018 9241 US 1 Gradient Echo Train Length
+0018 9301 SQ 1 CT Acquisition Type Sequence
+0018 9302 CS 1 Acquisition Type
+0018 9303 FD 1 Tube Angle
+0018 9304 SQ 1 CT Acquisition Details Sequence
+0018 9305 FD 1 Revolution Time
+0018 9306 FD 1 Single Collimation Width
+0018 9307 FD 1 Total Collimation Width
+0018 9308 SQ 1 CT Table Dynamics Sequence
+0018 9309 FD 1 Table Speed
+0018 9310 FD 1 Table Feed per Rotation
+0018 9311 FD 1 Spiral Pitch Factor
+0018 9312 SQ 1 CT Geometry Sequence
+0018 9313 FD 3 Data Collection Center (Patient)
+0018 9314 SQ 1 CT Reconstruction Sequence
+0018 9315 CS 1 Reconstruction Algorithm
+0018 9316 CS 1 Convolution Kernel Group
+0018 9317 FD 2 Reconstruction Field of View
+0018 9318 FD 3 Reconstruction Target Center (Patient)
+0018 9319 FD 1 Reconstruction Angle
+0018 9320 SH 1 Image Filter
+0018 9321 SQ 1 CT Exposure Sequence
+0018 9322 FD 2 Reconstruction Pixel Spacing
+0018 9323 CS 1 Exposure Modulation Type
+0018 9324 FD 1 Estimated Dose Saving
+0018 9325 SQ 1 CT X-ray Details Sequence
+0018 9326 SQ 1 CT Position Sequence
+0018 9327 FD 1 Table Position
+0018 9328 FD 1 Exposure Time in ms
+0018 9329 SQ 1 CT Image Frame Type Sequence
+0018 9330 FD 1 X-Ray Tube Current in mA
+0018 9332 FD 1 Exposure in mAs
+0018 9333 CS 1 Constant Volume Flag
+0018 9334 CS 1 Fluoroscopy Flag
+0018 9335 FD 1 Distance Source to Data Collection Center
+0018 9337 US 1 Contrast/Bolus Agent Number
+0018 9338 SQ 1 Contrast/Bolus Ingredient Code Sequence
+0018 9340 SQ 1 Contrast Administration Profile Sequence
+0018 9341 SQ 1 Contrast/Bolus Usage Sequence
+0018 9342 CS 1 Contrast/Bolus Agent Administered
+0018 9343 CS 1 Contrast/Bolus Agent Detected
+0018 9344 CS 1 Contrast/Bolus Agent Phase
+0018 9345 FD 1 CTDIvol
+0018 a001 SQ 1 Contributing Equipment Sequence
+0018 a002 DT 1 Contribution Date Time
+0018 a003 ST 1 Contribution Description
+
+0020 0000 UL 1 Group Length 
+0020 000d UI 1 Study Instance UID
+0020 000e UI 1 Series Instance UID
+0020 0010 SH 1 Study ID
+0020 0011 IS 1 Series Number
+0020 0012 IS 1 Acquisition Number
+0020 0013 IS 1 Instance Number
+0020 0014 IS 1 Isotope Number (RET)
+0020 0015 IS 1 Phase Number (RET)
+0020 0016 IS 1 Interval Number (RET)
+0020 0017 IS 1 Time Slot Number (RET)
+0020 0018 IS 1 Angle Number (RET)
+0020 0019 IS 1 Item Number
+0020 0020 CS 2 Patient Orientation
+0020 0022 IS 1 Overlay Number
+0020 0024 IS 1 Curve Number
+0020 0026 IS 1 Lookup Table Number
+0020 0030 DS 3 Image Position (RET)
+0020 0032 DS 3 Image Position (Patient)
+0020 0035 DS 6 Image Orientation (RET)
+0020 0037 DS 6 Image Orientation (Patient)
+0020 0050 DS 1 Location (RET)
+0020 0052 UI 1 Frame of Reference UID
+0020 0060 CS 1 Laterality
+0020 0062 CS 1 Image Laterality
+0020 0070 LO 1 Image Geometry Type (RET)
+0020 0080 LT 1-n Masking Image (RET)
+0020 0100 IS 1 Temporal Position Identifier
+0020 0105 IS 1 Number of Temporal Positions
+0020 0110 DS 1 Temporal Resolution
+0020 0200 UI 1 Synchronization Frame of Reference UID
+0020 1000 IS 1 Series in Study
+0020 1001 IS 1 Acquisitions in Series (RET)
+0020 1002 IS 1 Images in Acquisition
+0020 1003 IS 1 Images in Series FIXME (RET)
+0020 1004 IS 1 Acquisitions in Study
+0020 1005 IS 1 Images in Study FIXME (RET)
+0020 1020 LO 1-n Reference (RET)
+0020 1040 LO 1 Position Reference Indicator
+0020 1041 DS 1 Slice Location
+0020 1070 IS 1-n Other Study Numbers
+0020 1200 IS 1 Number of Patient Related Studies
+0020 1202 IS 1 Number of Patient Related Series
+0020 1204 IS 1 Number of Patient Related Instances
+0020 1206 IS 1 Number of Study Related Series
+0020 1208 IS 1 Number of Study Related Instances
+0020 1209 IS 1 Number of Series Related Instances
+0020 3100 LO 1-n Source Image IDs (RET)
+0020 3401 LO 1 Modifying Device ID (RET)
+0020 3402 LO 1 Modified Image ID (RET)
+0020 3403 DA 1 Modified Image Date (RET)
+0020 3404 LT 1 Modifying Device Manufacturer (RET)
+0020 3405 TM 1 Modified Image Time (RET)
+0020 3406 LT 1 Modified Image Description (RET)
+0020 4000 LT 1 Image Comments
+0020 5000 AT 1-n Original Image Identification (RET)
+0020 5002 LO 1-n Original Image Identification Nomenclature (RET)
+0020 9056 SH 1 Stack ID
+0020 9057 UL 1 In-Stack Position Number
+0020 9071 SQ 1 Frame Anatomy Sequence
+0020 9072 CS 1 Frame Laterality
+0020 9111 SQ 1 Frame Content Sequence
+0020 9113 SQ 1 Plane Position Sequence
+0020 9116 SQ 1 Plane Orientation Sequence
+0020 9128 UL 1 Temporal Position Index
+0020 9153 FD 1 Trigger Delay Time
+0020 9156 US 1 Frame Acquisition Number
+0020 9157 UL 1-n Dimension Index Values
+0020 9158 LT 1 Frame Comments
+0020 9161 UI 1 Concatenation UID
+0020 9162 US 1 In-concatenation Number
+0020 9163 US 1 In-concatenation Total Number
+0020 9164 UI 1 Dimension Organization UID
+0020 9165 AT 1 Dimension Index Pointer
+0020 9167 AT 1 Functional Group Pointer
+0020 9213 LO 1 Dimension Index Private Creator
+0020 9221 SQ 1 Dimension Organization Sequence
+0020 9222 SQ 1 Dimension Index Sequence
+0020 9228 UL 1 Concatenation Frame Offset Number
+0020 9238 LO 1 Functional Group Private Creator
+
+0022 0001 US 1 Light Path Filter Pass-Through Wavelength
+0022 0002 US 2 Light Path Filter Pass Band
+0022 0003 US 1 Image Path Filter Pass-Through Wavelength
+0022 0004 US 2 Image Path Filter Pass Band
+0022 0005 CS 1 Patient Eye Movement Commanded
+0022 0006 SQ 1 Patient Eye Movement Command Code Sequence
+0022 0007 FL 1 Spherical Lens Power
+0022 0008 FL 1 Cylinder Lens Power
+0022 0009 FL 1 Cylinder Axis
+0022 000a FL 1 Emmetropic Magnification
+0022 000b FL 1 Intra Ocular Pressure
+0022 000c FL 1 Horizontal Field of View
+0022 000d CS 1 Pupil Dilated
+0022 000e FL 1 Degree of Dilation
+0022 0010 FL 1 Stereo Baseline Angle
+0022 0011 FL 1 Stereo Baseline Displacement
+0022 0012 FL 1 Stereo Horizontal Pixel Offset
+0022 0013 FL 1 Stereo Vertical Pixel Offset
+0022 0014 FL 1 Stereo Rotation
+0022 0015 SQ 1 Acquisition Device Type Code Sequence
+0022 0016 SQ 1 Illumination Type Code Sequence
+0022 0017 SQ 1 Light Path Filter Type Stack Code Sequence
+0022 0018 SQ 1 Image Path Filter Type Stack Code Sequence
+0022 0019 SQ 1 Lenses Code Sequence
+0022 001a SQ 1 Channel Description Code Sequence
+0022 001b SQ 1 Refractive State Sequence
+0022 001c SQ 1 Mydriatic Agent Code Sequence
+0022 001d SQ 1 Relative Image Position Code Sequence
+0022 0020 SQ 1 Stereo Pairs Sequence
+0022 0021 SQ 1 Left Image Sequence
+0022 0022 SQ 1 Right Image Sequence
+
+0028 0000 UL 1 Group Length
+0028 0002 US 1 Samples per Pixel
+0028 0003 US 1 Samples per Pixel Used
+0028 0004 CS 1 Photometric Interpretation
+0028 0005 SS 1 Image Dimensions (RET)
+0028 0006 US 1 Planar Configuration
+0028 0008 IS 1 Number of Frames
+0028 0009 AT 1-n Frame Increment Pointer
+0028 000a AT 1-n Frame Dimension Pointer
+0028 0010 US 1 Rows
+0028 0011 US 1 Columns
+0028 0012 US 1 Planes
+0028 0014 US 1 Ultrasound Color Data Present
+0028 0030 DS 2 Pixel Spacing
+0028 0031 DS 2 Zoom Factor
+0028 0032 DS 2 Zoom Center
+0028 0034 IS 2 Pixel Aspect Ratio
+0028 0040 SH 1 Image Format (RET)
+0028 0050 LO 1-n Manipulated Image (RET)
+0028 0051 CS 1-n Corrected Image
+0028 0060 SH 1 Compression Code (RET)
+0028 0100 US 1 Bits Allocated
+0028 0101 US 1 Bits Stored
+0028 0102 US 1 High Bit
+0028 0103 US 1 Pixel Representation
+0028 0104 SS 1 Smallest Valid Pixel Value (RET)
+0028 0105 SS 1 Largest Valid Pixel Value (RET)
+0028 0106 SS 1 Smallest Image Pixel Value
+0028 0107 SS 1 Largest Image Pixel Value
+0028 0108 SS 1 Smallest Pixel Value in Series
+0028 0109 SS 1 Largest Pixel Value in Series
+0028 0110 SS 1 Smallest Image Pixel Value in Plane
+0028 0111 SS 1 Largest Image Pixel Value in Plane
+0028 0120 SS 1 Pixel Padding Value
+0028 0200 SS 1 Image Location (RET)
+0028 0300 CS 1 Quality Control Image
+0028 0301 CS 1 Burned In Annotation
+0028 1040 CS 1 Pixel Intensity Relationship
+0028 1041 SS 1 Pixel Intensity Relationship Sign
+0028 1050 DS 1-n Window Center
+0028 1051 DS 1-n Window Width
+0028 1052 DS 1 Rescale Intercept
+0028 1053 DS 1 Rescale Slope
+0028 1054 LO 1 Rescale Type
+0028 1055 LO 1-n Window Center & Width Explanation
+0028 1080 LT 1 Gray Scale (RET)
+0028 1090 CS 1 Recommended Viewing Mode
+0028 1100 US 3 Gray Lookup Table Descriptor (RET)
+0028 1101 US 3 Red Palette Color Lookup Table Descriptor
+0028 1102 US 3 Green Palette Color Lookup Table Descriptor
+0028 1103 US 3 Blue Palette Color Lookup Table Descriptor
+0028 1199 UI 1 Palette Color Lookup Table UID
+0028 1200 OW 1 Gray Lookup Table Data (RET)
+0028 1201 OW 1 Red Palette Color Lookup Table Data
+0028 1202 OW 1 Green Palette Color Lookup Table Data
+0028 1203 OW 1 Blue Palette Color Lookup Table Data
+0028 1221 OW 1 Segmented Red Palette Color Lookup Table Data
+0028 1222 OW 1 Segmented Green Palette Color Lookup Table Data
+0028 1223 OW 1 Segmented Blue Palette Color Lookup Table Data
+0028 1300 CS 1 Implant Present
+0028 1350 CS 1 Partial View
+0028 1351 ST 1 Partial View Description
+0028 2110 CS 1 Lossy Image Compression
+0028 2112 DS 1-n Lossy Image Compression Ratio
+0028 2114 CS 1-n Lossy Image Compression Method
+0028 3000 SQ 1 Modality LUT Sequence
+0028 3002 US 3 LUT Descriptor
+0028 3003 LO 1 LUT Explanation
+0028 3004 LO 1 Modality LUT Type
+0028 3006 OW 1 LUT Data
+0028 3010 SQ 1 VOI LUT Sequence
+0028 3110 SQ 1 Softcopy VOI LUT Sequence
+0028 4000 LT 1-n Image Presentation Comments (RET)
+0028 5000 SQ 1 Bi-Plane Acquisition Sequence
+0028 6010 US 1 Representative Frame Number
+0028 6020 US 1-n Frame Numbers of Interest (FOI)
+0028 6022 LO 1-n Frame(s) of Interest Description
+0028 6023 CS 1-n Frame of Interest Type
+0028 6030 US 1-n Mask Pointer(s) (RET)
+0028 6040 US 1-n R Wave Pointer
+0028 6100 SQ 1 Mask Subtraction Sequence
+0028 6101 CS 1 Mask Operation
+0028 6102 US 2-2n Applicable Frame Range
+0028 6110 US 1-n Mask Frame Numbers
+0028 6112 US 1 Contrast Frame Averaging
+0028 6114 FL 2 Mask Sub-pixel Shift
+0028 6120 SS 1 TID Offset
+0028 6190 ST 1 Mask Operation Explanation
+0028 9001 UL 1 Data Point Rows
+0028 9002 UL 1 Data Point Columns
+0028 9003 CS 1 Signal Domain Columns
+0028 9099 US 1 Largest Monochrome Pixel Value (RET)
+0028 9108 CS 1 Data Representation
+0028 9110 SQ 1 Pixel Measures Sequence
+0028 9132 SQ 1 Frame VOI LUT Sequence
+0028 9145 SQ 1 Pixel Value Transformation Sequence
+0028 9235 CS 1 Signal Domain Rows
+
+0032 0000 UL 1 Study Group Length
+0032 000a CS 1 Study Status ID
+0032 000c CS 1 Study Priority ID
+0032 0012 LO 1 Study ID Issuer
+0032 0032 DA 1 Study Verified Date
+0032 0033 TM 1 Study Verified Time
+0032 0034 DA 1 Study Read Date
+0032 0035 TM 1 Study Read Time
+0032 1000 DA 1 Scheduled Study Start Date
+0032 1001 TM 1 Scheduled Study Start Time
+0032 1010 DA 1 Scheduled Study Stop Date
+0032 1011 TM 1 Scheduled Study Stop Time
+0032 1020 LO 1 Scheduled Study Location
+0032 1021 AE 1-n Scheduled Study Location AE Title(s)
+0032 1030 LO 1 Reason for Study
+0032 1031 SQ 1 Requesting Physician Identification Sequence
+0032 1032 PN 1 Requesting Physician
+0032 1033 LO 1 Requesting Service
+0032 1040 DA 1 Study Arrival Date
+0032 1041 TM 1 Study Arrival Time
+0032 1050 DA 1 Study Completion Date
+0032 1051 TM 1 Study Completion Time
+0032 1055 CS 1 Study Component Status ID
+0032 1060 LO 1 Requested Procedure Description
+0032 1064 SQ 1 Requested Procedure Code Sequence
+0032 1070 LO 1 Requested Contrast Agent
+0032 4000 LT 1 Study Comments
+
+0038 0000 UL 1 Group Length
+0038 0004 SQ 1 Referenced Patient Alias Sequence
+0038 0008 CS 1 Visit Status ID
+0038 0010 LO 1 Admission ID
+0038 0011 LO 1 Issuer of Admission ID
+0038 0016 LO 1 Route of Admissions
+0038 001a DA 1 Scheduled Admission Date
+0038 001b TM 1 Scheduled Admission Time
+0038 001c DA 1 Scheduled Discharge Date
+0038 001d TM 1 Scheduled Discharge Time
+0038 001e LO 1 Scheduled Patient Institution Residence
+0038 0020 DA 1 Admitting Date
+0038 0021 TM 1 Admitting Time
+0038 0030 DA 1 Discharge Date
+0038 0032 TM 1 Discharge Time
+0038 0040 LO 1 Discharge Diagnosis Description
+0038 0044 SQ 1 Discharge Diagnosis Code Sequence
+0038 0050 LO 1 Special Needs
+0038 0300 LO 1 Current Patient Location
+0038 0400 LO 1 Patient's Institution Residence
+0038 0500 LO 1 Patient State
+0038 4000 LT 1 Visit Comments
+
+003a 0000 UL 1 Group Length
+003a 0004 CS 1 Waveform Originality
+003a 0005 US 1 Number of Waveform Channels
+003a 0010 UL 1 Number of Waveform Samples
+003a 001a DS 1 Sampling Frequency
+003a 0020 SH 1 Multiplex Group Label
+003a 0200 SQ 1 Channel Definition Sequence
+003a 0202 IS 1 Waveform Channel Number
+003a 0203 SH 1 Channel Label
+003a 0205 CS 1-n Channel Status
+003a 0208 SQ 1 Channel Source Sequence
+003a 0209 SQ 1 Channel Source Modifiers Sequence
+003a 020a SQ 1 Source Waveform Sequence
+003a 020c LO 1 Channel Derivation Description
+003a 0210 DS 1 Channel Sensitivity
+003a 0211 SQ 1 Channel Sensitivity Units Sequence
+003a 0212 DS 1 Channel Sensitivity Correction Factor
+003a 0213 DS 1 Channel Baseline
+003a 0214 DS 1 Channel Time Skew
+003a 0215 DS 1 Channel Sample Skew
+003a 0218 DS 1 Channel Offset
+003a 021a US 1 Waveform Bits Stored
+003a 0220 DS 1 Filter Low Frequency
+003a 0221 DS 1 Filter High Frequency
+003a 0222 DS 1 Notch Filter Frequency
+003a 0223 DS 1 Notch Filter Bandwidth
+003a 0300 SQ 1 Multiplexed Audio Channels Description Code Sequence
+003a 0301 IS 1 Channel Identification Code
+003a 0302 CS 1 Channel Mode
+
+0040 0000 UL 1 Group Length
+0040 0001 AE 1-n Scheduled Station AE Title
+0040 0002 DA 1 Scheduled Procedure Step Start Date
+0040 0003 TM 1 Scheduled Procedure Step Start Time
+0040 0004 DA 1 Scheduled Procedure Step End Date
+0040 0005 TM 1 Scheduled Procedure Step End Time
+0040 0006 PN 1 Scheduled Performing Physician's Name
+0040 0007 LO 1 Scheduled Procedure Step Description
+0040 0008 SQ 1 Scheduled Protocol Code Sequence
+0040 0009 SH 1 Scheduled Procedure Step ID
+0040 000a SQ 1 Stage Code Sequence
+0040 000b SQ 1 Scheduled Performing Physician Identification Sequence
+0040 0010 SH 1-n Scheduled Station Name
+0040 0011 SH 1 Scheduled Procedure Step Location
+0040 0012 LO 1 Pre-Medication
+0040 0020 CS 1 Scheduled Procedure Step Status
+0040 0100 SQ 1 Scheduled Procedure Step Sequence
+0040 0220 SQ 1 Referenced Non-Image Composite SOP Instance Sequence
+0040 0241 AE 1 Performed Station AE Title
+0040 0242 SH 1 Performed Station Name
+0040 0243 SH 1 Performed Location
+0040 0244 DA 1 Performed Procedure Step Start Date
+0040 0245 TM 1 Performed Procedure Step Start Time
+0040 0250 DA 1 Performed Procedure Step End Date
+0040 0251 TM 1 Performed Procedure Step End Time
+0040 0252 CS 1 Performed Procedure Step Status
+0040 0253 SH 1 Performed Procedure Step ID
+0040 0254 LO 1 Performed Procedure Step Description
+0040 0255 LO 1 Performed Procedure Type Description
+0040 0260 SQ 1 Performed Protocol Code Sequence
+0040 0270 SQ 1 Scheduled Step Attributes Sequence
+0040 0275 SQ 1 Request Attributes Sequence
+0040 0280 ST 1 Comments on the Performed Procedure Step
+0040 0281 SQ 1 Performed Procedure Step Discontinuation Reason Code Sequence
+0040 0293 SQ 1 Quantity Sequence
+0040 0294 DS 1 Quantity
+0040 0295 SQ 1 Measuring Units Sequence
+0040 0296 SQ 1 Billing Item Sequence
+0040 0300 US 1 Total Time of Fluoroscopy
+0040 0301 US 1 Total Number of Exposures
+0040 0302 US 1 Entrance Dose
+0040 0303 US 1-2 Exposed Area
+0040 0306 DS 1 Distance Source to Entrance
+0040 0307 DS 1 Distance Source to Support (RET)
+0040 030e SQ 1 Exposure Dose Sequence
+0040 0310 ST 1 Comments on Radiation Dose
+0040 0312 DS 1 X-Ray Output
+0040 0314 DS 1 Half Value Layer
+0040 0316 DS 1 Organ Dose
+0040 0318 CS 1 Organ Exposed
+0040 0320 SQ 1 Billing Procedure Step Sequence
+0040 0321 SQ 1 Film Consumption Sequence
+0040 0324 SQ 1 Billing Supplies and Devices Sequence
+0040 0330 SQ 1 Referenced Procedure Step Sequence (RET)
+0040 0340 SQ 1 Performed Series Sequence
+0040 0400 LT 1 Comments on the Scheduled Procedure Step
+0040 0440 SQ 1 Protocol Context Sequence
+0040 0441 SQ 1 Content Item Modifier Sequence
+0040 050a LO 1 Specimen Accession Number
+0040 0550 SQ 1 Specimen Sequence
+0040 0551 LO 1 Specimen Identifier
+0040 0555 SQ 1 Acquisition Context Sequence
+0040 0556 ST 1 Acquisition Context Description
+0040 059a SQ 1 Specimen Type Code Sequence
+0040 06fa LO 1 Slide Identifier
+0040 071a SQ 1 Image Center Point Coordinates Sequence
+0040 072a DS 1 X offset in Slide Coordinate System
+0040 073a DS 1 Y offset in Slide Coordinate System
+0040 074a DS 1 Z offset in Slide Coordinate System
+0040 08d8 SQ 1 Pixel Spacing Sequence
+0040 08da SQ 1 Coordinate System Axis Code Sequence
+0040 08ea SQ 1 Measurement Units Code Sequence
+0040 1001 SH 1 Requested Procedure ID
+0040 1002 LO 1 Reason for the Requested Procedure
+0040 1003 SH 1 Requested Procedure Priority
+0040 1004 LO 1 Patient Transport Arrangements
+0040 1005 LO 1 Requested Procedure Location
+0040 1006 SH 1 Placer Order Number / Procedure (RET)
+0040 1007 SH 1 Filler Order Number / Procedure (RET)
+0040 1008 LO 1 Confidentiality Code
+0040 1009 SH 1 Reporting Priority
+0040 100a SQ 1 Reason for Requested Procedure Code Sequence
+0040 1010 PN 1-n Names of Intended Recipients of Results
+0040 1011 SQ 1 Intended Recipients of Results Identification Sequence
+0040 1101 SQ 1 Person Identification Code Sequence
+0040 1102 ST 1 Person's Address
+0040 1103 LO 1-n Person's Telephone Numbers
+0040 1400 LT 1 Requested Procedure Comments
+0040 2001 LO 1 Reason for the Imaging Service Request (RET)
+0040 2004 DA 1 Issue Date of Imaging Service Request
+0040 2005 TM 1 Issue Time of Imaging Service Request
+0040 2006 SH 1 Placer Order Number / Imaging Service Request (RET)
+0040 2007 SH 1 Filler Order Number / Imaging Service Request (RET)
+0040 2008 PN 1 Order Entered By
+0040 2009 SH 1 Order Enterer's Location
+0040 2010 SH 1 Order Callback Phone Number
+0040 2016 LO 1 Placer Order Number / Imaging Service Request
+0040 2017 LO 1 Filler Order Number / Imaging Service Request
+0040 2400 LT 1 Imaging Service Request Comments
+0040 3001 LO 1 Confidentiality Constraint on Patient Data Description
+0040 4001 CS 1 General Purpose Scheduled Procedure Step Status
+0040 4002 CS 1 General Purpose Performed Procedure Step Status
+0040 4003 CS 1 General Purpose Scheduled Procedure Step Priority
+0040 4004 SQ 1 Scheduled Processing Applications Code Sequence
+0040 4005 DT 1 Scheduled Procedure Step Start Date and Time
+0040 4006 CS 1 Multiple Copies Flag
+0040 4007 SQ 1 Performed Processing Applications Code Sequence
+0040 4009 SQ 1 Human Performer Code Sequence
+0040 4010 DT 1 Scheduled Procedure Step Modification Date and Time
+0040 4011 DT 1 Expected Completion Date and Time
+0040 4015 SQ 1 Resulting General Purpose Performed Procedure Steps Sequence
+0040 4016 SQ 1 Referenced General Purpose Scheduled Procedure Step Sequence
+0040 4018 SQ 1 Scheduled Workitem Code Sequence
+0040 4019 SQ 1 Performed Workitem Code Sequence
+0040 4020 CS 1 Input Availability Flag
+0040 4021 SQ 1 Input Information Sequence
+0040 4022 SQ 1 Relevant Information Sequence
+0040 4023 UI 1 Referenced General Purpose Scheduled Procedure Step Transaction UID
+0040 4025 SQ 1 Scheduled Station Name Code Sequence
+0040 4026 SQ 1 Scheduled Station Class Code Sequence
+0040 4027 SQ 1 Scheduled Station Geographic Location Code Sequence
+0040 4028 SQ 1 Performed Station Name Code Sequence
+0040 4029 SQ 1 Performed Station Class Code Sequence
+0040 4030 SQ 1 Performed Station Geographic Location Code Sequence
+0040 4031 SQ 1 Requested Subsequent Workitem Code Sequence
+0040 4032 SQ 1 Non-DICOM Output Code Sequence
+0040 4033 SQ 1 Output Information Sequence
+0040 4034 SQ 1 Scheduled Human Performers Sequence
+0040 4035 SQ 1 Actual Human Performers Sequence
+0040 4036 LO 1 Human Performer's Organization
+0040 4037 PN 1 Human Performer's Name
+0040 8302 DS 1 Entrance Dose in mGy
+0040 9096 SQ 1 Real World Value Mapping Sequence
+0040 9210 SH 1 LUT Label
+0040 9211 US 1 Real World Value Last Value Mapped
+0040 9212 FD 1-n Real World Value LUT Data
+0040 9216 US 1 Real World Value First Value Mapped
+0040 9224 FD 1 Real World Value Intercept
+0040 9225 FD 1 Real World Value Slope
+0040 a010 CS 1 Relationship Type
+0040 a027 LO 1 Verifying Organization
+0040 a030 DT 1 Verification Date Time
+0040 a032 DT 1 Observation Date Time
+0040 a040 CS 1 Value Type
+0040 a043 SQ 1 Concept Name Code Sequence
+0040 a050 CS 1 Continuity Of Content
+0040 a073 SQ 1 Verifying Observer Sequence
+0040 a075 PN 1 Verifying Observer Name
+0040 a088 SQ 1 Verifying Observer Identification Code Sequence
+0040 a0b0 US 2-2n Referenced Waveform Channels
+0040 a120 DT 1 DateTime
+0040 a121 DA 1 Date
+0040 a122 TM 1 Time
+0040 a123 PN 1 Person Name
+0040 a124 UI 1 UID
+0040 a130 CS 1 Temporal Range Type
+0040 a132 UL 1-n Referenced Sample Positions
+0040 a136 US 1-n Referenced Frame Numbers
+0040 a138 DS 1-n Referenced Time Offsets
+0040 a13a DT 1-n Referenced Datetime
+0040 a160 UT 1 Text Value
+0040 a168 SQ 1 Concept Code Sequence
+0040 a170 SQ 1 Purpose of Reference Code Sequence
+0040 a180 US 1 Annotation Group Number
+0040 a195 SQ 1 Modifier Code Sequence
+0040 a300 SQ 1 Measured Value Sequence
+0040 a301 SQ 1 Numeric Value Qualifier Code Sequence
+0040 a30a DS 1-n Numeric Value
+0040 a360 SQ 1 Predecessor Documents Sequence
+0040 a370 SQ 1 Referenced Request Sequence
+0040 a372 SQ 1 Performed Procedure Code Sequence
+0040 a375 SQ 1 Current Requested Procedure Evidence Sequence
+0040 a385 SQ 1 Pertinent Other Evidence Sequence
+0040 a491 CS 1 Completion Flag
+0040 a492 LO 1 Completion Flag Description
+0040 a493 CS 1 Verification Flag
+0040 a504 SQ 1 Content Template Sequence
+0040 a525 SQ 1 Identical Documents Sequence
+0040 a730 SQ 1 Content Sequence
+0040 b020 SQ 1 Annotation Sequence
+0040 db00 CS 1 Template Identifier
+0040 db06 DT 1 Template Version (RET)
+0040 db07 DT 1 Template Local Version (RET)
+0040 db0b CS 1 Template Extension Flag (RET)
+0040 db0c UI 1 Template Extension Organization UID (RET)
+0040 db0d UI 1 Template Extension Creator UID (RET)
+0040 db73 UL 1-n Referenced Content Item Identifier
+
+0050 0000 UL 1 Group Length
+0050 0004 CS 1 Calibration Image
+0050 0010 SQ 1 Device Sequence
+0050 0014 DS 1 Device Length
+0050 0016 DS 1 Device Diameter
+0050 0017 CS 1 Device Diameter Units
+0050 0018 DS 1 Device Volume
+0050 0019 DS 1 Inter-Marker Distance
+0050 0020 LO 1 Device Description
+
+0054 0000 UL 1 Group Length
+0054 0010 US 1-n Energy Window Vector
+0054 0011 US 1 Number of Energy Windows
+0054 0012 SQ 1 Energy Window Information Sequence
+0054 0013 SQ 1 Energy Window Range Sequence
+0054 0014 DS 1 Energy Window Lower Limit
+0054 0015 DS 1 Energy Window Upper Limit
+0054 0016 SQ 1 Radiopharmaceutical Information Sequence
+0054 0017 IS 1 Residual Syringe Counts
+0054 0018 SH 1 Energy Window Name
+0054 0020 US 1-n Detector Vector
+0054 0021 US 1 Number of Detectors
+0054 0022 SQ 1 Detector Information Sequence
+0054 0030 US 1-n Phase Vector
+0054 0031 US 1 Number of Phases
+0054 0032 SQ 1 Phase Information Sequence
+0054 0033 US 1 Number of Frames in Phase
+0054 0036 IS 1 Phase Delay
+0054 0038 IS 1 Pause Between Frames
+0054 0039 CS 1 Phase Description
+0054 0050 US 1-n Rotation Vector
+0054 0051 US 1 Number of Rotations
+0054 0052 SQ 1 Rotation Information Sequence
+0054 0053 US 1 Number of Frames in Rotation
+0054 0060 US 1-n R-R Interval Vector
+0054 0061 US 1 Number of R-R Intervals
+0054 0062 SQ 1 Gated Information Sequence
+0054 0063 SQ 1 Data Information Sequence
+0054 0070 US 1-n Time Slot Vector
+0054 0071 US 1 Number of Time Slots
+0054 0072 SQ 1 Time Slot Information Sequence
+0054 0073 DS 1 Time Slot Time
+0054 0080 US 1-n Slice Vector
+0054 0081 US 1 Number of Slices
+0054 0090 US 1-n Angular View Vector
+0054 0100 US 1-n Time Slice Vector
+0054 0101 US 1 Number of Time Slices
+0054 0200 DS 1 Start Angle
+0054 0202 CS 1 Type of Detector Motion
+0054 0210 IS 1-n Trigger Vector
+0054 0211 US 1 Number of Triggers in Phase
+0054 0220 SQ 1 View Code Sequence
+0054 0222 SQ 1 View Modifier Code Sequence
+0054 0300 SQ 1 Radionuclide Code Sequence
+0054 0302 SQ 1 Administration Route Code Sequence
+0054 0304 SQ 1 Radiopharmaceutical Code Sequence
+0054 0306 SQ 1 Calibration Data Sequence
+0054 0308 US 1 Energy Window Number
+0054 0400 SH 1 Image ID
+0054 0410 SQ 1 Patient Orientation Code Sequence
+0054 0412 SQ 1 Patient Orientation Modifier Code Sequence
+0054 0414 SQ 1 Patient Gantry Relationship Code Sequence
+0054 0500 CS 1 Slice Progression Direction
+0054 1000 CS 2 Series Type
+0054 1001 CS 1 Units
+0054 1002 CS 1 Counts Source
+0054 1004 CS 1 Reprojection Method
+0054 1100 CS 1 Randoms Correction Method
+0054 1101 LO 1 Attenuation Correction Method
+0054 1102 CS 1 Decay Correction
+0054 1103 LO 1 Reconstruction Method
+0054 1104 LO 1 Detector Lines of Response Used
+0054 1105 LO 1 Scatter Correction Method
+0054 1200 DS 1 Axial Acceptance
+0054 1201 IS 2 Axial Mash
+0054 1202 IS 1 Transverse Mash
+0054 1203 DS 2 Detector Element Size
+0054 1210 DS 1 Coincidence Window Width
+0054 1220 CS 1-n Secondary Counts Type
+0054 1300 DS 1 Frame Reference Time
+0054 1310 IS 1 Primary (Prompts) Counts Accumulated
+0054 1311 IS 1-n Secondary Counts Accumulated
+0054 1320 DS 1 Slice Sensitivity Factor
+0054 1321 DS 1 Decay Factor
+0054 1322 DS 1 Dose Calibration Factor
+0054 1323 DS 1 Scatter Fraction Factor
+0054 1324 DS 1 Dead Time Factor
+0054 1330 US 1 Image Index
+0054 1400 CS 1-n Counts Included
+0054 1401 CS 1 Dead Time Correction Flag
+
+0060 0000 UL 1 Group Length
+0060 3000 SQ 1 Histogram Sequence
+0060 3002 US 1 Histogram Number of Bins
+0060 3004 US 1 Histogram First Bin Value
+0060 3006 US 1 Histogram Last Bin Value
+0060 3008 US 1 Histogram Bin Width
+0060 3010 LO 1 Histogram Explanation
+0060 3020 UL 1-n Histogram Data
+
+0070 0000 UL 1 Group Length
+0070 0001 SQ 1 Graphic Annotation Sequence
+0070 0002 CS 1 Graphic Layer
+0070 0003 CS 1 Bounding Box Annotation Units
+0070 0004 CS 1 Anchor Point Annotation Units
+0070 0005 CS 1 Graphic Annotation Units
+0070 0006 ST 1 Unformatted Text Value
+0070 0008 SQ 1 Text Object Sequence
+0070 0009 SQ 1 Graphic Object Sequence
+0070 0010 FL 2 Bounding Box Top Left Hand Corner
+0070 0011 FL 2 Bounding Box Bottom Right Hand Corner
+0070 0012 CS 1 Bounding Box Text Horizontal Justification
+0070 0014 FL 2 Anchor Point
+0070 0015 CS 1 Anchor Point Visibility
+0070 0020 US 1 Graphic Dimensions
+0070 0021 US 1 Number of Graphic Points
+0070 0022 FL 2-n Graphic Data
+0070 0023 CS 1 Graphic Type
+0070 0024 CS 1 Graphic Filled
+0070 0041 CS 1 Image Horizontal Flip
+0070 0042 US 1 Image Rotation
+0070 0052 SL 2 Displayed Area Top Left Hand Corner
+0070 0053 SL 2 Displayed Area Bottom Right Hand Corner
+0070 005a SQ 1 Displayed Area Selection Sequence
+0070 0060 SQ 1 Graphic Layer Sequence
+0070 0062 IS 1 Graphic Layer Order
+0070 0066 US 1 Graphic Layer Recommended Display Grayscale Value
+0070 0067 US 3 Graphic Layer Recommended Display RGB Value
+0070 0068 LO 1 Graphic Layer Description
+0070 0080 CS 1 Content Label
+0070 0081 LO 1 Content Description
+0070 0082 DA 1 Presentation Creation Date
+0070 0083 TM 1 Presentation Creation Time
+0070 0084 PN 1 Content Creator's Name
+0070 0100 CS 1 Presentation Size Mode
+0070 0101 DS 2 Presentation Pixel Spacing
+0070 0102 IS 2 Presentation Pixel Aspect Ratio
+0070 0103 FL 1 Presentation Pixel Magnification Ratio
+0070 0306 CS 1 Shape Type
+0070 0308 SQ 1 Registration Sequence
+0070 0309 SQ 1 Matrix Registration Sequence
+0070 030a SQ 1 Matrix Sequence
+0070 030c CS 1 Frame of Reference Transformation Matrix Type
+0070 030d SQ 1 Registration Type Code Sequence
+0070 030f ST 1 Fiducial Description
+0070 0310 SH 1 Fiducial Identifier
+0070 0311 SQ 1 Fiducial Identifier Code Sequence
+0070 0312 FD 1 Contour Uncertainty Radius
+0070 0314 SQ 1 Used Fiducials Sequence
+0070 0318 SQ 1 Graphic Coordinates Data Sequence
+0070 031a UI 1 Fiducial UID
+0070 031c SQ 1 Fiducial Set Sequence
+0070 031e SQ 1 Fiducial Sequence
+
+0088 0000 UL 1 Group Length
+0088 0130 SH 1 Storage Media File-set ID
+0088 0140 UI 1 Storage Media File-set UID
+0088 0200 SQ 1 Icon Image Sequence
+0088 0904 LO 1 Topic Title
+0088 0906 ST 1 Topic Subject
+0088 0910 LO 1 Topic Author
+0088 0912 LO 1-32 Topic Keywords
+
+0100 0000 UL 1 Group Length
+0100 0410 CS 1 SOP Instance Status
+0100 0420 DT 1 SOP Authorization Date and Time
+0100 0424 LT 1 SOP Authorization Comment
+0100 0426 LO 1 Authorization Equipment Certification Number
+
+0400 0000 UL 1 Group Length
+0400 0005 US 1 MAC ID Number
+0400 0010 UI 1 MAC Calculation Transfer Syntax UID
+0400 0015 CS 1 MAC Algorithm
+0400 0020 AT 1-n Data Elements Signed
+0400 0100 UI 1 Digital Signature UID
+0400 0105 DT 1 Digital Signature DateTime
+0400 0110 CS 1 Certificate Type
+0400 0115 OB 1 Certificate of Signer
+0400 0120 OB 1 Signature
+0400 0305 CS 1 Certified Timestamp Type
+0400 0310 OB 1 Certified Timestamp
+0400 0500 SQ 1 Encrypted Attributes Sequence
+0400 0510 UI 1 Encrypted Content Transfer Syntax UID
+0400 0520 OB 1 Encrypted Content
+0400 0550 SQ 1 Modified Attributes Sequence
+
+2000 0000 UL 1 Group Length
+2000 0010 IS 1 Number of Copies
+2000 001e SQ 1 Printer Configuration Sequence
+2000 0020 CS 1 Print Priority
+2000 0030 CS 1 Medium Type
+2000 0040 CS 1 Film Destination
+2000 0050 LO 1 Film Session Label
+2000 0060 IS 1 Memory Allocation
+2000 0061 IS 1 Maximum Memory Allocation
+2000 0062 CS 1 Color Image Printing Flag
+2000 0063 CS 1 Collation Flag
+2000 0065 CS 1 Annotation Flag
+2000 0067 CS 1 Image Overlay Flag
+2000 0069 CS 1 Presentation LUT Flag
+2000 006a CS 1 Image Box Presentation LUT Flag
+2000 00a0 US 1 Memory Bit Depth
+2000 00a1 US 1 Printing Bit Depth
+2000 00a2 SQ 1 Media Installed Sequence
+2000 00a4 SQ 1 Other Media Available Sequence
+2000 00a8 SQ 1 Supported Image Display Formats Sequence
+2000 0500 SQ 1 Referenced Film Box Sequence
+2000 0510 SQ 1 Referenced Stored Print Sequence
+
+2010 0000 UL 1 Group Length
+2010 0010 ST 1 Image Display Format
+2010 0030 CS 1 Annotation Display Format ID
+2010 0040 CS 1 Film Orientation
+2010 0050 CS 1 Film Size ID
+2010 0052 CS 1 Printer Resolution ID
+2010 0054 CS 1 Default Printer Resolution ID
+2010 0060 CS 1 Magnification Type
+2010 0080 CS 1 Smoothing Type
+2010 00a6 CS 1 Default Magnification Type
+2010 00a7 CS 1-n Other Magnification Types Available
+2010 00a8 CS 1 Default Smoothing Type
+2010 00a9 CS 1-n Other Smoothing Types Available
+2010 0100 CS 1 Border Density
+2010 0110 CS 1 Empty Image Density
+2010 0120 US 1 Min Density
+2010 0130 US 1 Max Density
+2010 0140 CS 1 Trim
+2010 0150 ST 1 Configuration Information
+2010 0152 LT 1 Configuration Information Description
+2010 0154 IS 1 Maximum Collated Films
+2010 015e US 1 Illumination
+2010 0160 US 1 Reflected Ambient Light
+2010 0376 DS 2 Printer Pixel Spacing
+2010 0500 SQ 1 Referenced Film Session Sequence
+2010 0510 SQ 1 Referenced Image Box Sequence
+2010 0520 SQ 1 Referenced Basic Annotation Box Sequence
+
+2020 0000 UL 1 Group Length
+2020 0010 US 1 Image Position
+2020 0020 CS 1 Polarity
+2020 0030 DS 1 Requested Image Size
+2020 0040 CS 1 Requested Decimate/Crop Behavior
+2020 0050 CS 1 Requested Resolution ID
+2020 00a0 CS 1 Requested Image Size Flag
+2020 00a2 CS 1 Decimate/Crop Result
+2020 0110 SQ 1 Basic Grayscale Image Sequence
+2020 0111 SQ 1 Basic Color Image Sequence
+2020 0130 SQ 1 Referenced Image Overlay Box Sequence (RET)
+2020 0140 SQ 1 Referenced VOI LUT Box Sequence (RET)
+
+2030 0000 UL 1 Group Length
+2030 0010 US 1 Annotation Position
+2030 0020 LO 1 Text String
+
+2040 0000 UL 1 Group Length
+2040 0010 SQ 1 Referenced Overlay Plane Sequence
+2040 0011 US 1-99 Referenced Overlay Plane Groups
+2040 0020 SQ 1 Overlay Pixel Data Sequence
+2040 0060 CS 1 Overlay Magnification Type
+2040 0070 CS 1 Overlay Smoothing Type
+2040 0072 CS 1 Overlay or Image Magnification
+2040 0074 US 1 Magnify to Number of Columns
+2040 0080 CS 1 Overlay Foreground Density
+2040 0082 CS 1 Overlay Background Density
+2040 0090 CS 1 Overlay Mode (RET)
+2040 0100 CS 1 Threshold Density (RET)
+2040 0500 SQ 1 Referenced Image Box Sequence (RET)
+
+2050 0000 UL 1 Group Length
+2050 0010 SQ 1 Presentation LUT Sequence
+2050 0020 CS 1 Presentation LUT Shape
+2050 0500 SQ 1 Referenced Presentation LUT Sequence
+
+2100 0000 UL 1 Group Length
+2100 0010 SH 1 Print Job ID
+2100 0020 CS 1 Execution Status
+2100 0030 CS 1 Execution Status Info
+2100 0040 DA 1 Creation Date
+2100 0050 TM 1 Creation Time
+2100 0070 AE 1 Originator
+2100 0140 AE 1 Destination AE
+2100 0160 SH 1 Owner ID
+2100 0170 IS 1 Number of Films
+2100 0500 SQ 1 Referenced Print Job Sequence
+
+2110 0000 UL 1 Group Length
+2110 0010 CS 1 Printer Status
+2110 0020 CS 1 Printer Status Info
+2110 0030 LO 1 Printer Name
+2110 0099 SH 1 Print Queue ID
+
+2120 0000 UL 1 Group Length
+2120 0010 CS 1 Queue Status
+2120 0050 SQ 1 Print Job Description Sequence
+2120 0070 SQ 1 Referenced Print Job Sequence
+
+2130 0000 UL 1 Group Length
+2130 0010 SQ 1 Print Management Capabilities Sequence
+2130 0015 SQ 1 Printer Characteristics Sequence
+2130 0030 SQ 1 Film Box Content Sequence
+2130 0040 SQ 1 Image Box Content Sequence
+2130 0050 SQ 1 Annotation Content Sequence
+2130 0060 SQ 1 Image Overlay Box Content Sequence
+2130 0080 SQ 1 Presentation LUT Content Sequence
+2130 00a0 SQ 1 Proposed Study Sequence
+2130 00c0 SQ 1 Original Image Sequence
+
+2200 0000 UL 1 Group Length
+2200 0001 CS 1 Label Using Information Extracted From Instances
+2200 0002 UT 1 Label Text
+2200 0003 CS 1 Label Style Selection
+2200 0004 LT 1 Media Disposition
+2200 0005 LT 1 Barcode Value
+2200 0006 CS 1 Barcode Symbology
+2200 0007 CS 1 Allow Media Splitting
+2200 0008 CS 1 Include Non-DICOM Objects
+2200 0009 CS 1 Include Display Application
+2200 000a CS 1 Preserve Composite Instances After Media Creation
+2200 000b US 1 Total Number of Pieces of Media Created
+2200 000c LO 1 Requested Media Application Profile
+2200 000d SQ 1 Referenced Storage Media Sequence
+2200 000e AT 1-n Failure Attributes
+2200 000f CS 1 Allow Lossy Compression
+2200 0020 CS 1 Request Priority
+
+3002 0000 UL 1 Group Length
+3002 0002 SH 1 RT Image Label
+3002 0003 LO 1 RT Image Name
+3002 0004 ST 1 RT Image Description
+3002 000a CS 1 Reported Values Origin
+3002 000c CS 1 RT Image Plane
+3002 000d DS 3 X-Ray Image Receptor Translation
+3002 000e DS 1 X-Ray Image Receptor Angle
+3002 0010 DS 6 RT Image Orientation
+3002 0011 DS 2 Image Plane Pixel Spacing
+3002 0012 DS 2 RT Image Position
+3002 0020 SH 1 Radiation Machine Name
+3002 0022 DS 1 Radiation Machine SAD
+3002 0024 DS 1 Radiation Machine SSD
+3002 0026 DS 1 RT Image SID
+3002 0028 DS 1 Source to Reference Object Distance
+3002 0029 IS 1 Fraction Number
+3002 0030 SQ 1 Exposure Sequence
+3002 0032 DS 1 Meterset Exposure
+3002 0034 DS 4 Diaphragm Position
+3002 0040 SQ 1 Fluence Map Sequence
+3002 0041 CS 1 Fluence Data Source
+3002 0042 DS 1 Fluence Data Scale
+
+3004 0000 UL 1 DVH Group Length
+3004 0001 CS 1 DVH Type
+3004 0002 CS 1 Dose Units
+3004 0004 CS 1 Dose Type
+3004 0006 LO 1 Dose Comment
+3004 0008 DS 3 Normalization Point
+3004 000a CS 1 Dose Summation Type
+3004 000c DS 2-n Grid Frame Offset Vector
+3004 000e DS 1 Dose Grid Scaling
+3004 0010 SQ 1 RT Dose ROI Sequence
+3004 0012 DS 1 Dose Value
+3004 0014 CS 1-3 Tissue Heterogeneity Correction
+3004 0040 DS 3 DVH Normalization Point
+3004 0042 DS 1 DVH Normalization Dose Value
+3004 0050 SQ 1 DVH Sequence
+3004 0052 DS 1 DVH Dose Scaling
+3004 0054 CS 1 DVH Volume Units
+3004 0056 IS 1 DVH Number of Bins
+3004 0058 DS 2-2n DVH Data
+3004 0060 SQ 1 DVH Referenced ROI Sequence
+3004 0062 CS 1 DVH ROI Contribution Type
+3004 0070 DS 1 DVH Minimum Dose
+3004 0072 DS 1 DVH Maximum Dose
+3004 0074 DS 1 DVH Mean Dose
+
+3006 0000 UL 1 Group Length
+3006 0002 SH 1 Structure Set Label
+3006 0004 LO 1 Structure Set Name
+3006 0006 ST 1 Structure Set Description
+3006 0008 DA 1 Structure Set Date
+3006 0009 TM 1 Structure Set Time
+3006 0010 SQ 1 Referenced Frame of Reference Sequence
+3006 0012 SQ 1 RT Referenced Study Sequence
+3006 0014 SQ 1 RT Referenced Series Sequence
+3006 0016 SQ 1 Contour Image Sequence
+3006 0020 SQ 1 Structure Set ROI Sequence
+3006 0022 IS 1 ROI Number
+3006 0024 UI 1 Referenced Frame of Reference UID
+3006 0026 LO 1 ROI Name
+3006 0028 ST 1 ROI Description
+3006 002a IS 3 ROI Display Color
+3006 002c DS 1 ROI Volume
+3006 0030 SQ 1 RT Related ROI Sequence
+3006 0033 CS 1 RT ROI Relationship
+3006 0036 CS 1 ROI Generation Algorithm
+3006 0038 LO 1 ROI Generation Description
+3006 0039 SQ 1 ROI Contour Sequence
+3006 0040 SQ 1 Contour Sequence
+3006 0042 CS 1 Contour Geometric Type
+3006 0044 DS 1 Contour Slab Thickness
+3006 0045 DS 3 Contour Offset Vector
+3006 0046 IS 1 Number of Contour Points
+3006 0048 IS 1 Contour Number
+3006 0049 IS 1-n Attached Contours
+3006 0050 DS 3-3n Contour Data
+3006 0080 SQ 1 RT ROI Observations Sequence
+3006 0082 IS 1 Observation Number
+3006 0084 IS 1 Referenced ROI Number
+3006 0085 SH 1 ROI Observation Label
+3006 0086 SQ 1 RT ROI Identification Code Sequence
+3006 0088 ST 1 ROI Observation Description
+3006 00a0 SQ 1 Related RT ROI Observations Sequence
+3006 00a4 CS 1 RT ROI Interpreted Type
+3006 00a6 PN 1 ROI Interpreter
+3006 00b0 SQ 1 ROI Physical Properties Sequence
+3006 00b2 CS 1 ROI Physical Property
+3006 00b4 DS 1 ROI Physical Property Value
+3006 00c0 SQ 1 Frame of Reference Relationship Sequence
+3006 00c2 UI 1 Related Frame of Reference UID
+3006 00c4 CS 1 Frame of Reference Transformation Type
+3006 00c6 DS 16 Frame of Reference Transformation Matrix
+3006 00c8 LO 1 Frame of Reference Transformation Comment
+
+3008 0000 UL 1 Group Length
+3008 0010 SQ 1 Measured Dose Reference Sequence
+3008 0012 ST 1 Measured Dose Description
+3008 0014 CS 1 Measured Dose Type
+3008 0016 DS 1 Measured Dose Value
+3008 0020 SQ 1 Treatment Session Beam Sequence
+3008 0022 IS 1 Current Fraction Number
+3008 0024 DA 1 Treatment Control Point Date
+3008 0025 TM 1 Treatment Control Point Time
+3008 002a CS 1 Treatment Termination Status
+3008 002b SH 1 Treatment Termination Code
+3008 002c CS 1 Treatment Verification Status
+3008 0030 SQ 1 Referenced Treatment Record Sequence
+3008 0032 DS 1 Specified Primary Meterset
+3008 0033 DS 1 Specified Secondary Meterset
+3008 0036 DS 1 Delivered Primary Meterset
+3008 0037 DS 1 Delivered Secondary Meterset
+3008 003a DS 1 Specified Treatment Time
+3008 003b DS 1 Delivered Treatment Time
+3008 0040 SQ 1 Control Point Delivery Sequence
+3008 0042 DS 1 Specified Meterset
+3008 0044 DS 1 Delivered Meterset
+3008 0048 DS 1 Dose Rate Delivered
+3008 0050 SQ 1 Treatment Summary Calculated Dose Reference Sequence
+3008 0052 DS 1 Cumulative Dose to Dose Reference
+3008 0054 DA 1 First Treatment Date
+3008 0056 DA 1 Most Recent Treatment Date
+3008 005a IS 1 Number of Fractions Delivered
+3008 0060 SQ 1 Override Sequence
+3008 0062 AT 1 Override Parameter Pointer
+3008 0064 IS 1 Measured Dose Reference Number
+3008 0066 ST 1 Override Reason
+3008 0070 SQ 1 Calculated Dose Reference Sequence
+3008 0072 IS 1 Calculated Dose Reference Number
+3008 0074 ST 1 Calculated Dose Reference Description
+3008 0076 DS 1 Calculated Dose Reference Dose Value
+3008 0078 DS 1 Start Meterset
+3008 007a DS 1 End Meterset
+3008 0080 SQ 1 Referenced Measured Dose Reference Sequence
+3008 0082 IS 1 Referenced Measured Dose Reference Number
+3008 0090 SQ 1 Referenced Calculated Dose Reference Sequence
+3008 0092 IS 1 Referenced Calculated Dose Reference Number
+3008 00a0 SQ 1 Beam Limiting Device Leaf Pairs Sequence
+3008 00b0 SQ 1 Recorded Wedge Sequence
+3008 00c0 SQ 1 Recorded Compensator Sequence
+3008 00d0 SQ 1 Recorded Block Sequence
+3008 00e0 SQ 1 Treatment Summary Measured Dose Reference Sequence
+3008 0100 SQ 1 Recorded Source Sequence
+3008 0105 LO 1 Source Serial Number
+3008 0110 SQ 1 Treatment Session Application Setup Sequence
+3008 0116 CS 1 Application Setup Check
+3008 0120 SQ 1 Recorded Brachy Accessory Device Sequence
+3008 0122 IS 1 Referenced Brachy Accessory Device Number
+3008 0130 SQ 1 Recorded Channel Sequence
+3008 0132 DS 1 Specified Channel Total Time
+3008 0134 DS 1 Delivered Channel Total Time
+3008 0136 IS 1 Specified Number of Pulses
+3008 0138 IS 1 Delivered Number of Pulses
+3008 013a DS 1 Specified Pulse Repetition Interval
+3008 013c DS 1 Delivered Pulse Repetition Interval
+3008 0140 SQ 1 Recorded Source Applicator Sequence
+3008 0142 IS 1 Referenced Source Applicator Number
+3008 0150 SQ 1 Recorded Channel Shield Sequence
+3008 0152 IS 1 Referenced Channel Shield Number
+3008 0160 SQ 1 Brachy Control Point Delivered Sequence
+3008 0162 DA 1 Safe Position Exit Date
+3008 0164 TM 1 Safe Position Exit Time
+3008 0166 DA 1 Safe Position Return Date
+3008 0168 TM 1 Safe Position Return Time
+3008 0200 CS 1 Current Treatment Status
+3008 0202 ST 1 Treatment Status Comment
+3008 0220 SQ 1 Fraction Group Summary Sequence
+3008 0223 IS 1 Referenced Fraction Number
+3008 0224 CS 1 Fraction Group Type
+3008 0230 CS 1 Beam Stopper Position
+3008 0240 SQ 1 Fraction Status Summary Sequence
+3008 0250 DA 1 Treatment Date
+3008 0251 TM 1 Treatment Time
+
+300a 0000 UL 1 Group Length
+300a 0002 SH 1 RT Plan Label
+300a 0003 LO 1 RT Plan Name
+300a 0004 ST 1 RT Plan Description
+300a 0006 DA 1 RT Plan Date
+300a 0007 TM 1 RT Plan Time
+300a 0009 LO 1-n Treatment Protocols
+300a 000a CS 1 Treatment Intent
+300a 000b LO 1-n Treatment Sites
+300a 000c CS 1 RT Plan Geometry
+300a 000e ST 1 Prescription Description
+300a 0010 SQ 1 Dose Reference Sequence
+300a 0012 IS 1 Dose Reference Number
+300a 0013 UI 1 Dose Reference UID
+300a 0014 CS 1 Dose Reference Structure Type
+300a 0015 CS 1 Nominal Beam Energy Unit
+300a 0016 LO 1 Dose Reference Description
+300a 0018 DS 3 Dose Reference Point Coordinates
+300a 001a DS 1 Nominal Prior Dose
+300a 0020 CS 1 Dose Reference Type
+300a 0021 DS 1 Constraint Weight
+300a 0022 DS 1 Delivery Warning Dose
+300a 0023 DS 1 Delivery Maximum Dose
+300a 0025 DS 1 Target Minimum Dose
+300a 0026 DS 1 Target Prescription Dose
+300a 0027 DS 1 Target Maximum Dose
+300a 0028 DS 1 Target Underdose Volume Fraction
+300a 002a DS 1 Organ at Risk Full-volume Dose
+300a 002b DS 1 Organ at Risk Limit Dose
+300a 002c DS 1 Organ at Risk Maximum Dose
+300a 002d DS 1 Organ at Risk Overdose Volume Fraction
+300a 0040 SQ 1 Tolerance Table Sequence
+300a 0042 IS 1 Tolerance Table Number
+300a 0043 SH 1 Tolerance Table Label
+300a 0044 DS 1 Gantry Angle Tolerance
+300a 0046 DS 1 Beam Limiting Device Angle Tolerance
+300a 0048 SQ 1 Beam Limiting Device Tolerance Sequence
+300a 004a DS 1 Beam Limiting Device Position Tolerance
+300a 004c DS 1 Patient Support Angle Tolerance
+300a 004e DS 1 Table Top Eccentric Angle Tolerance
+300a 0051 DS 1 Table Top Vertical Position Tolerance
+300a 0052 DS 1 Table Top Longitudinal Position Tolerance
+300a 0053 DS 1 Table Top Lateral Position Tolerance
+300a 0055 CS 1 RT Plan Relationship
+300a 0070 SQ 1 Fraction Group Sequence
+300a 0071 IS 1 Fraction Group Number
+300a 0072 LO 1 Fraction Group Description
+300a 0078 IS 1 Number of Fractions Planned
+300a 0079 IS 1 Number of Fraction Pattern Digits Per Day
+300a 007a IS 1 Repeat Fraction Cycle Length
+300a 007b LT 1 Fraction Pattern
+300a 0080 IS 1 Number of Beams
+300a 0082 DS 3 Beam Dose Specification Point
+300a 0084 DS 1 Beam Dose
+300a 0086 DS 1 Beam Meterset
+300a 00a0 IS 1 Number of Brachy Application Setups
+300a 00a2 DS 3 Brachy Application Setup Dose Specification Point
+300a 00a4 DS 1 Brachy Application Setup Dose
+300a 00b0 SQ 1 Beam Sequence
+300a 00b2 SH 1 Treatment Machine Name
+300a 00b3 CS 1 Primary Dosimeter Unit
+300a 00b4 DS 1 Source-Axis Distance
+300a 00b6 SQ 1 Beam Limiting Device Sequence
+300a 00b8 CS 1 RT Beam Limiting Device Type
+300a 00ba DS 1 Source to Beam Limiting Device Distance
+300a 00bc IS 1 Number of Leaf/Jaw Pairs
+300a 00be DS 3-n Leaf Position Boundaries
+300a 00c0 IS 1 Beam Number
+300a 00c2 LO 1 Beam Name
+300a 00c3 ST 1 Beam Description
+300a 00c4 CS 1 Beam Type
+300a 00c6 CS 1 Radiation Type
+300a 00c7 CS 1 High-Dose Technique Type
+300a 00c8 IS 1 Reference Image Number
+300a 00ca SQ 1 Planned Verification Image Sequence
+300a 00cc LO 1-n Imaging Device-Specific Acquisition Parameters
+300a 00ce CS 1 Treatment Delivery Type
+300a 00d0 IS 1 Number of Wedges
+300a 00d1 SQ 1 Wedge Sequence
+300a 00d2 IS 1 Wedge Number
+300a 00d3 CS 1 Wedge Type
+300a 00d4 SH 1 Wedge ID
+300a 00d5 IS 1 Wedge Angle
+300a 00d6 DS 1 Wedge Factor
+300a 00d8 DS 1 Wedge Orientation
+300a 00da DS 1 Source to Wedge Tray Distance
+300a 00e0 IS 1 Number of Compensators
+300a 00e1 SH 1 Material ID
+300a 00e2 DS 1 Total Compensator Tray Factor
+300a 00e3 SQ 1 Compensator Sequence
+300a 00e4 IS 1 Compensator Number
+300a 00e5 SH 1 Compensator ID
+300a 00e6 DS 1 Source to Compensator Tray Distance
+300a 00e7 IS 1 Compensator Rows
+300a 00e8 IS 1 Compensator Columns
+300a 00e9 DS 2 Compensator Pixel Spacing
+300a 00ea DS 2 Compensator Position
+300a 00eb DS 1-n Compensator Transmission Data
+300a 00ec DS 1-n Compensator Thickness Data
+300a 00ed IS 1 Number of Boli
+300a 00ee CS 1 Compensator Type
+300a 00f0 IS 1 Number of Blocks
+300a 00f2 DS 1 Total Block Tray Factor
+300a 00f4 SQ 1 Block Sequence
+300a 00f5 SH 1 Block Tray ID
+300a 00f6 DS 1 Source to Block Tray Distance
+300a 00f8 CS 1 Block Type
+300a 00f9 LO 1 Accessory Code
+300a 00fa CS 1 Block Divergence
+300a 00fb CS 1 Block Mounting Position
+300a 00fc IS 1 Block Number
+300a 00fe LO 1 Block Name
+300a 0100 DS 1 Block Thickness
+300a 0102 DS 1 Block Transmission
+300a 0104 IS 1 Block Number of Points
+300a 0106 DS 2-2n Block Data
+300a 0107 SQ 1 Applicator Sequence
+300a 0108 SH 1 Applicator ID
+300a 0109 CS 1 Applicator Type
+300a 010a LO 1 Applicator Description
+300a 010c DS 1 Cumulative Dose Reference Coefficient
+300a 010e DS 1 Final Cumulative Meterset Weight
+300a 0110 IS 1 Number of Control Points
+300a 0111 SQ 1 Control Point Sequence
+300a 0112 IS 1 Control Point Index
+300a 0114 DS 1 Nominal Beam Energy
+300a 0115 DS 1 Dose Rate Set
+300a 0116 SQ 1 Wedge Position Sequence
+300a 0118 CS 1 Wedge Position
+300a 011a SQ 1 Beam Limiting Device Position Sequence
+300a 011c DS 2-2n Leaf/Jaw Positions
+300a 011e DS 1 Gantry Angle
+300a 011f CS 1 Gantry Rotation Direction
+300a 0120 DS 1 Beam Limiting Device Angle
+300a 0121 CS 1 Beam Limiting Device Rotation Direction
+300a 0122 DS 1 Patient Support Angle
+300a 0123 CS 1 Patient Support Rotation Direction
+300a 0124 DS 1 Table Top Eccentric Axis Distance
+300a 0125 DS 1 Table Top Eccentric Angle
+300a 0126 CS 1 Table Top Eccentric Rotation Direction
+300a 0128 DS 1 Table Top Vertical Position
+300a 0129 DS 1 Table Top Longitudinal Position
+300a 012a DS 1 Table Top Lateral Position
+300a 012c DS 3 Isocenter Position
+300a 012e DS 3 Surface Entry Point
+300a 0130 DS 1 Source to Surface Distance
+300a 0134 DS 1 Cumulative Meterset Weight
+300a 0180 SQ 1 Patient Setup Sequence
+300a 0182 IS 1 Patient Setup Number
+300a 0184 LO 1 Patient Additional Position
+300a 0190 SQ 1 Fixation Device Sequence
+300a 0192 CS 1 Fixation Device Type
+300a 0194 SH 1 Fixation Device Label
+300a 0196 ST 1 Fixation Device Description
+300a 0198 SH 1 Fixation Device Position
+300a 01a0 SQ 1 Shielding Device Sequence
+300a 01a2 CS 1 Shielding Device Type
+300a 01a4 SH 1 Shielding Device Label
+300a 01a6 ST 1 Shielding Device Description
+300a 01a8 SH 1 Shielding Device Position
+300a 01b0 CS 1 Setup Technique
+300a 01b2 ST 1 Setup Technique Description
+300a 01b4 SQ 1 Setup Device Sequence
+300a 01b6 CS 1 Setup Device Type
+300a 01b8 SH 1 Setup Device Label
+300a 01ba ST 1 Setup Device Description
+300a 01bc DS 1 Setup Device Parameter
+300a 01d0 ST 1 Setup Reference Description
+300a 01d2 DS 1 Table Top Vertical Setup Displacement
+300a 01d4 DS 1 Table Top Longitudinal Setup Displacement
+300a 01d6 DS 1 Table Top Lateral Setup Displacement
+300a 0200 CS 1 Brachy Treatment Technique
+300a 0202 CS 1 Brachy Treatment Type
+300a 0206 SQ 1 Treatment Machine Sequence
+300a 0210 SQ 1 Source Sequence
+300a 0212 IS 1 Source Number
+300a 0214 CS 1 Source Type
+300a 0216 LO 1 Source Manufacturer
+300a 0218 DS 1 Active Source Diameter
+300a 021a DS 1 Active Source Length
+300a 0222 DS 1 Source Encapsulation Nominal Thickness
+300a 0224 DS 1 Source Encapsulation Nominal Transmission
+300a 0226 LO 1 Source Isotope Name
+300a 0228 DS 1 Source Isotope Half Life
+300a 022a DS 1 Reference Air Kerma Rate
+300a 022c DA 1 Air Kerma Rate Reference Date
+300a 022e TM 1 Air Kerma Rate Reference Time
+300a 0230 SQ 1 Application Setup Sequence
+300a 0232 CS 1 Application Setup Type
+300a 0234 IS 1 Application Setup Number
+300a 0236 LO 1 Application Setup Name
+300a 0238 LO 1 Application Setup Manufacturer
+300a 0240 IS 1 Template Number
+300a 0242 SH 1 Template Type
+300a 0244 LO 1 Template Name
+300a 0250 DS 1 Total Reference Air Kerma
+300a 0260 SQ 1 Brachy Accessory Device Sequence
+300a 0262 IS 1 Brachy Accessory Device Number
+300a 0263 SH 1 Brachy Accessory Device ID
+300a 0264 CS 1 Brachy Accessory Device Type
+300a 0266 LO 1 Brachy Accessory Device Name
+300a 026a DS 1 Brachy Accessory Device Nominal Thickness
+300a 026c DS 1 Brachy Accessory Device Nominal Transmission
+300a 0280 SQ 1 Channel Sequence
+300a 0282 IS 1 Channel Number
+300a 0284 DS 1 Channel Length
+300a 0286 DS 1 Channel Total Time
+300a 0288 CS 1 Source Movement Type
+300a 028a IS 1 Number of Pulses
+300a 028c DS 1 Pulse Repetition Interval
+300a 0290 IS 1 Source Applicator Number
+300a 0291 SH 1 Source Applicator ID
+300a 0292 CS 1 Source Applicator Type
+300a 0294 LO 1 Source Applicator Name
+300a 0296 DS 1 Source Applicator Length
+300a 0298 LO 1 Source Applicator Manufacturer
+300a 029c DS 1 Source Applicator Wall Nominal Thickness
+300a 029e DS 1 Source Applicator Wall Nominal Transmission
+300a 02a0 DS 1 Source Applicator Step Size
+300a 02a2 IS 1 Transfer Tube Number
+300a 02a4 DS 1 Transfer Tube Length
+300a 02b0 SQ 1 Channel Shield Sequence
+300a 02b2 IS 1 Channel Shield Number
+300a 02b3 SH 1 Channel Shield ID
+300a 02b4 LO 1 Channel Shield Name
+300a 02b8 DS 1 Channel Shield Nominal Thickness
+300a 02ba DS 1 Channel Shield Nominal Transmission
+300a 02c8 DS 1 Final Cumulative Time Weight
+300a 02d0 SQ 1 Brachy Control Point Sequence
+300a 02d2 DS 1 Control Point Relative Position
+300a 02d4 DS 3 Control Point 3D Position
+300a 02d6 DS 1 Cumulative Time Weight
+300a 02e0 CS 1 Compensator Divergence
+300a 02e1 CS 1 Compensator Mounting Position
+300a 02e2 DS 1-n Source to Compensator Distance
+
+300c 0000 UL 1 Group Length
+300c 0002 SQ 1 Referenced RT Plan Sequence
+300c 0004 SQ 1 Referenced Beam Sequence
+300c 0006 IS 1 Referenced Beam Number
+300c 0007 IS 1 Referenced Reference Image Number
+300c 0008 DS 1 Start Cumulative Meterset Weight
+300c 0009 DS 1 End Cumulative Meterset Weight
+300c 000a SQ 1 Referenced Brachy Application Setup Sequence
+300c 000c IS 1 Referenced Brachy Application Setup Number
+300c 000e IS 1 Referenced Source Number
+300c 0020 SQ 1 Referenced Fraction Group Sequence
+300c 0022 IS 1 Referenced Fraction Group Number
+300c 0040 SQ 1 Referenced Verification Image Sequence
+300c 0042 SQ 1 Referenced Reference Image Sequence
+300c 0050 SQ 1 Referenced Dose Reference Sequence
+300c 0051 IS 1 Referenced Dose Reference Number
+300c 0055 SQ 1 Brachy Referenced Dose Reference Sequence
+300c 0060 SQ 1 Referenced Structure Set Sequence
+300c 006a IS 1 Referenced Patient Setup Number
+300c 0080 SQ 1 Referenced Dose Sequence
+300c 00a0 IS 1 Referenced Tolerance Table Number
+300c 00b0 SQ 1 Referenced Bolus Sequence
+300c 00c0 IS 1 Referenced Wedge Number
+300c 00d0 IS 1 Referenced Compensator Number
+300c 00e0 IS 1 Referenced Block Number
+300c 00f0 IS 1 Referenced Control Point Index
+
+300e 0000 UL 1 Group Length
+300e 0002 CS 1 Approval Status
+300e 0004 DA 1 Review Date
+300e 0005 TM 1 Review Time
+300e 0008 PN 1 Reviewer Name
+
+4000 0000 UL 1 Text Group Length
+4000 0010 LT 1-n Text Arbitrary (RET)
+4000 4000 LT 1-n Text Comments (RET)
+
+4008 0000 UL 1 Group Length
+4008 0040 SH 1 Results ID
+4008 0042 LO 1 Results ID Issuer
+4008 0050 SQ 1 Referenced Interpretation Sequence
+4008 0100 DA 1 Interpretation Recorded Date
+4008 0101 TM 1 Interpretation Recorded Time
+4008 0102 PN 1 Interpretation Recorder
+4008 0103 LO 1 Reference to Recorded Sound
+4008 0108 DA 1 Interpretation Transcription Date
+4008 0109 TM 1 Interpretation Transcription Time
+4008 010a PN 1 Interpretation Transcriber
+4008 010b ST 1 Interpretation Text
+4008 010c PN 1 Interpretation Author
+4008 0111 SQ 1 Interpretation Approver Sequence
+4008 0112 DA 1 Interpretation Approval Date
+4008 0113 TM 1 Interpretation Approval Time
+4008 0114 PN 1 Physician Approving Interpretation
+4008 0115 LT 1 Interpretation Diagnosis Description
+4008 0117 SQ 1 Interpretation Diagnosis Code Sequence
+4008 0118 SQ 1 Results Distribution List Sequence
+4008 0119 PN 1 Distribution Name
+4008 011a LO 1 Distribution Address
+4008 0200 SH 1 Interpretation ID
+4008 0202 LO 1 Interpretation ID Issuer
+4008 0210 CS 1 Interpretation Type ID
+4008 0212 CS 1 Interpretation Status ID
+4008 0300 ST 1 Impressions
+4008 4000 ST 1 Results Comments
+
+4ffe 0000 UL 1 Group Length
+4ffe 0001 SQ 1 MAC Parameters Sequence
+
+5000 0000 UL 1 Group Length
+5000 0005 US 1 Curve Dimensions
+5000 0010 US 1 Number of Points
+5000 0020 CS 1 Type of Data
+5000 0022 LO 1 Curve Description
+5000 0030 SH 1-n Axis Units
+5000 0040 SH 1-n Axis Labels
+5000 0103 US 1 Data Value Representation
+5000 0104 US 1-n Minimum Coordinate Value
+5000 0105 US 1-n Maximum Coordinate Value
+5000 0106 SH 1-n Curve Range
+5000 0110 US 1-n Curve Data Descriptor
+5000 0112 US 1-n Coordinate Start Value
+5000 0114 US 1-n Coordinate Step Value
+5000 1001 CS 1 Curve Activation Layer
+5000 2000 US 1 Audio Type
+5000 2002 US 1 Audio Sample Format
+5000 2004 US 1 Number of Channels
+5000 2006 UL 1 Number of Samples
+5000 2008 UL 1 Sample Rate
+5000 200a UL 1 Total Time
+5000 200c OW 1 Audio Sample Data
+5000 200e LT 1 Audio Comments
+5000 2500 LO 1 Curve Label
+5000 2600 SQ 1 Referenced Overlay Sequence
+5000 2610 US 1 Referenced Overlay Group
+5000 3000 OW 1 Curve Data
+
+5002 0000 UL 1 Group Length
+5002 0005 US 1 Curve Dimensions
+5002 0010 US 1 Number of Points
+5002 0020 CS 1 Type of Data
+5002 0022 LO 1 Curve Description
+5002 0030 SH 1-n Axis Units
+5002 0040 SH 1-n Axis Labels
+5002 0103 US 1 Data Value Representation
+5002 0104 US 1-n Minimum Coordinate Value
+5002 0105 US 1-n Maximum Coordinate Value
+5002 0106 SH 1-n Curve Range
+5002 0110 US 1-n Curve Data Descriptor
+5002 0112 US 1-n Coordinate Start Value
+5002 0114 US 1-n Coordinate Step Value
+5002 2000 US 1 Audio Type
+5002 2002 US 1 Audio Sample Format
+5002 2004 US 1 Number of Channels
+5002 2006 UL 1 Number of Samples
+5002 2008 UL 1 Sample Rate
+5002 200a UL 1 Total Time
+5002 200c OW 1 Audio Sample Data
+5002 200e LT 1 Audio Comments
+5002 2500 LO 1 Curve Label
+5002 2600 SQ 1 Referenced Overlay Sequence
+5002 2610 US 1 Referenced Overlay Group
+5002 3000 OW 1 Curve Data
+
+5004 0000 UL 1 Group Length
+5004 0005 US 1 Curve Dimensions
+5004 0010 US 1 Number of Points
+5004 0020 CS 1 Type of Data
+5004 0022 LO 1 Curve Description
+5004 0030 SH 1-n Axis Units
+5004 0040 SH 1-n Axis Labels
+5004 0103 US 1 Data Value Representation
+5004 0104 US 1-n Minimum Coordinate Value
+5004 0105 US 1-n Maximum Coordinate Value
+5004 0106 SH 1-n Curve Range
+5004 0110 US 1-n Curve Data Descriptor
+5004 0112 US 1-n Coordinate Start Value
+5004 0114 US 1-n Coordinate Step Value
+5004 2000 US 1 Audio Type
+5004 2002 US 1 Audio Sample Format
+5004 2004 US 1 Number of Channels
+5004 2006 UL 1 Number of Samples
+5004 2008 UL 1 Sample Rate
+5004 200a UL 1 Total Time
+5004 200c OW 1 Audio Sample Data
+5004 200e LT 1 Audio Comments
+5004 2500 LO 1 Curve Label
+5004 2600 SQ 1 Referenced Overlay Sequence
+5004 2610 US 1 Referenced Overlay Group
+5004 3000 OW 1 Curve Data
+
+5006 0000 UL 1 Group Length
+5006 0005 US 1 Curve Dimensions
+5006 0010 US 1 Number of Points
+5006 0020 CS 1 Type of Data
+5006 0022 LO 1 Curve Description
+5006 0030 SH 1-n Axis Units
+5006 0040 SH 1-n Axis Labels
+5006 0103 US 1 Data Value Representation
+5006 0104 US 1-n Minimum Coordinate Value
+5006 0105 US 1-n Maximum Coordinate Value
+5006 0106 SH 1-n Curve Range
+5006 0110 US 1-n Curve Data Descriptor
+5006 0112 US 1-n Coordinate Start Value
+5006 0114 US 1-n Coordinate Step Value
+5006 2000 US 1 Audio Type
+5006 2002 US 1 Audio Sample Format
+5006 2004 US 1 Number of Channels
+5006 2006 UL 1 Number of Samples
+5006 2008 UL 1 Sample Rate
+5006 200a UL 1 Total Time
+5006 200c OW 1 Audio Sample Data
+5006 200e LT 1 Audio Comments
+5006 2500 LO 1 Curve Label
+5006 2600 SQ 1 Referenced Overlay Sequence
+5006 2610 US 1 Referenced Overlay Group
+5006 3000 OW 1 Curve Data
+
+5008 0000 UL 1 Group Length
+5008 0005 US 1 Curve Dimensions
+5008 0010 US 1 Number of Points
+5008 0020 CS 1 Type of Data
+5008 0022 LO 1 Curve Description
+5008 0030 SH 1-n Axis Units
+5008 0040 SH 1-n Axis Labels
+5008 0103 US 1 Data Value Representation
+5008 0104 US 1-n Minimum Coordinate Value
+5008 0105 US 1-n Maximum Coordinate Value
+5008 0106 SH 1-n Curve Range
+5008 0110 US 1-n Curve Data Descriptor
+5008 0112 US 1-n Coordinate Start Value
+5008 0114 US 1-n Coordinate Step Value
+5008 2000 US 1 Audio Type
+5008 2002 US 1 Audio Sample Format
+5008 2004 US 1 Number of Channels
+5008 2006 UL 1 Number of Samples
+5008 2008 UL 1 Sample Rate
+5008 200a UL 1 Total Time
+5008 200c OW 1 Audio Sample Data
+5008 200e LT 1 Audio Comments
+5008 2500 LO 1 Curve Label
+5008 2600 SQ 1 Referenced Overlay Sequence
+5008 2610 US 1 Referenced Overlay Group
+5008 3000 OW 1 Curve Data
+
+500a 0000 UL 1 Group Length
+500a 0005 US 1 Curve Dimensions
+500a 0010 US 1 Number of Points
+500a 0020 CS 1 Type of Data
+500a 0022 LO 1 Curve Description
+500a 0030 SH 1-n Axis Units
+500a 0040 SH 1-n Axis Labels
+500a 0103 US 1 Data Value Representation
+500a 0104 US 1-n Minimum Coordinate Value
+500a 0105 US 1-n Maximum Coordinate Value
+500a 0106 SH 1-n Curve Range
+500a 0110 US 1-n Curve Data Descriptor
+500a 0112 US 1-n Coordinate Start Value
+500a 0114 US 1-n Coordinate Step Value
+500a 2000 US 1 Audio Type
+500a 2002 US 1 Audio Sample Format
+500a 2004 US 1 Number of Channels
+500a 2006 UL 1 Number of Samples
+500a 2008 UL 1 Sample Rate
+500a 200a UL 1 Total Time
+500a 200c OW 1 Audio Sample Data
+500a 200e LT 1 Audio Comments
+500a 2500 LO 1 Curve Label
+500a 2600 SQ 1 Referenced Overlay Sequence
+500a 2610 US 1 Referenced Overlay Group
+500a 3000 OW 1 Curve Data
+
+500c 0000 UL 1 Group Length
+500c 0005 US 1 Curve Dimensions
+500c 0010 US 1 Number of Points
+500c 0020 CS 1 Type of Data
+500c 0022 LO 1 Curve Description
+500c 0030 SH 1-n Axis Units
+500c 0040 SH 1-n Axis Labels
+500c 0103 US 1 Data Value Representation
+500c 0104 US 1-n Minimum Coordinate Value
+500c 0105 US 1-n Maximum Coordinate Value
+500c 0106 SH 1-n Curve Range
+500c 0110 US 1-n Curve Data Descriptor
+500c 0112 US 1-n Coordinate Start Value
+500c 0114 US 1-n Coordinate Step Value
+500c 2000 US 1 Audio Type
+500c 2002 US 1 Audio Sample Format
+500c 2004 US 1 Number of Channels
+500c 2006 UL 1 Number of Samples
+500c 2008 UL 1 Sample Rate
+500c 200a UL 1 Total Time
+500c 200c OW 1 Audio Sample Data
+500c 200e LT 1 Audio Comments
+500c 2500 LO 1 Curve Label
+500c 2600 SQ 1 Referenced Overlay Sequence
+500c 2610 US 1 Referenced Overlay Group
+500c 3000 OW 1 Curve Data
+
+500e 0000 UL 1 Group Length
+500e 0005 US 1 Curve Dimensions
+500e 0010 US 1 Number of Points
+500e 0020 CS 1 Type of Data
+500e 0022 LO 1 Curve Description
+500e 0030 SH 1-n Axis Units
+500e 0040 SH 1-n Axis Labels
+500e 0103 US 1 Data Value Representation
+500e 0104 US 1-n Minimum Coordinate Value
+500e 0105 US 1-n Maximum Coordinate Value
+500e 0106 SH 1-n Curve Range
+500e 0110 US 1-n Curve Data Descriptor
+500e 0112 US 1-n Coordinate Start Value
+500e 0114 US 1-n Coordinate Step Value
+500e 2000 US 1 Audio Type
+500e 2002 US 1 Audio Sample Format
+500e 2004 US 1 Number of Channels
+500e 2006 UL 1 Number of Samples
+500e 2008 UL 1 Sample Rate
+500e 200a UL 1 Total Time
+500e 200c OW 1 Audio Sample Data
+500e 200e LT 1 Audio Comments
+500e 2500 LO 1 Curve Label
+500e 2600 SQ 1 Referenced Overlay Sequence
+500e 2610 US 1 Referenced Overlay Group
+500e 3000 OW 1 Curve Data
+
+5200 0000 UL 1 Group Length
+5200 9229 SQ 1 Shared Functional Groups Sequence
+5200 9230 SQ 1 Per-frame Functional Groups Sequence
+
+5400 0000 UL 1 Group Length
+5400 0100 SQ 1 Waveform Sequence
+5400 0110 OB 1 Channel Minimum Value
+5400 0112 OB 1 Channel Maximum Value
+5400 1004 US 1 Waveform Bits Allocated
+5400 1006 CS 1 Waveform Sample Interpretation
+5400 100a OB 1 Waveform Padding Value
+5400 1010 OB 1 Waveform Data
+
+5600 0000 UL 1 Group Length
+5600 0010 OF 1 First Order Phase Correction Angle
+5600 0020 OF 1 Spectroscopy Data
+
+6000 0000 UL 1 Group Length
+6000 0010 US 1 Overlay Rows
+6000 0011 US 1 Overlay Columns
+6000 0012 US 1 Overlay Planes
+6000 0015 IS 1 Number of Frames in Overlay
+6000 0022 LO 1 Overlay Description
+6000 0040 CS 1 Overlay Type
+6000 0045 LO 1 Overlay Subtype
+6000 0050 SS 2 Overlay Origin
+6000 0051 US 1 Image Frame Origin
+6000 0052 US 1 Overlay Plane Origin
+6000 0060 LT 1 Overlay Compression Code (RET)
+6000 0100 US 1 Overlay Bits Allocated
+6000 0102 US 1 Overlay Bit Position
+6000 0110 LT 1 Overlay Format (RET)
+6000 0200 US 1 Overlay Location (RET)
+6000 1001 CS 1 Overlay Activation Layer
+6000 1100 US 1 Overlay Descriptor - Gray (RET)
+6000 1101 US 1 Overlay Descriptor - Red (RET)
+6000 1102 US 1 Overlay Descriptor - Green (RET)
+6000 1103 US 1 Overlay Descriptor - Blue (RET)
+6000 1200 US 1-n Overlays - Gray (RET)
+6000 1201 US 1-n Overlays - Red (RET)
+6000 1202 US 1-n Overlays - Green (RET)
+6000 1203 US 1-n Overlays - Blue (RET)
+6000 1301 IS 1 ROI Area
+6000 1302 DS 1 ROI Mean
+6000 1303 DS 1 ROI Standard Deviation
+6000 1500 LO 1 Overlay Label
+6000 3000 OW 1 Overlay Data
+6000 4000 LT 1-n Overlay Comments (RET)
+
+6002 0000 UL 1 Group Length
+6002 0010 US 1 Rows
+6002 0011 US 1 Columns
+6002 0012 US 1 Planes
+6002 0015 IS 1 Number of Frames in Overlay
+6002 0022 LO 1 Overlay Description
+6002 0040 CS 1 Overlay Type
+6002 0045 LO 1 Overlay Subtype
+6002 0050 SS 2 Overlay Origin
+6002 0051 US 1 Image Frame Origin
+6002 0052 US 1 Overlay Plane Origin
+6002 0060 LT 1 Overlay Compression Code (RET)
+6002 0100 US 1 Overlay Bits Allocated
+6002 0102 US 1 Overlay Bit Position
+6002 0110 LT 1 Overlay Format (RET)
+6002 0200 US 1 Overlay Location (RET)
+6002 1001 US 1 Overlay Activation Layer
+6002 1100 US 1 Overlay Descriptor - Gray (RET)
+6002 1101 US 1 Overlay Descriptor - Red (RET)
+6002 1102 US 1 Overlay Descriptor - Green (RET)
+6002 1103 US 1 Overlay Descriptor - Blue (RET)
+6002 1200 US 1-n Overlays - Gray
+6002 1201 US 1-n Overlays - Red
+6002 1202 US 1-n Overlays - Green
+6002 1203 US 1-n Overlays - Blue
+6002 1301 IS 1 ROI Area
+6002 1302 DS 1 ROI Mean
+6002 1303 DS 1 ROI Standard Deviation
+6002 1500 LO 1 Overlay Label
+6002 3000 OW 1 Overlay Data
+6002 4000 LT 1-n Overlay Comments (RET)
+
+6004 0000 UL 1 Group Length
+6004 0010 US 1 Rows
+6004 0011 US 1 Columns
+6004 0012 US 1 Planes
+6004 0015 IS 1 Number of Frames in Overlay
+6004 0022 LO 1 Overlay Description
+6004 0040 CS 1 Overlay Type
+6004 0045 LO 1 Overlay Subtype
+6004 0050 SS 2 Overlay Origin
+6004 0051 US 1 Image Frame Origin
+6004 0052 US 1 Overlay Plane Origin
+6004 0060 LT 1 Overlay Compression Code (RET)
+6004 0100 US 1 Overlay Bits Allocated
+6004 0102 US 1 Overlay Bit Position
+6004 0110 LT 1 Overlay Format (RET)
+6004 0200 US 1 Overlay Location (RET)
+6004 1001 US 1 Overlay Activation Layer
+6004 1100 US 1 Overlay Descriptor - Gray (RET)
+6004 1101 US 1 Overlay Descriptor - Red (RET)
+6004 1102 US 1 Overlay Descriptor - Green (RET)
+6004 1103 US 1 Overlay Descriptor - Blue (RET)
+6004 1200 US 1-n Overlays - Gray
+6004 1201 US 1-n Overlays - Red
+6004 1202 US 1-n Overlays - Green
+6004 1203 US 1-n Overlays - Blue
+6004 1301 IS 1 ROI Area
+6004 1302 DS 1 ROI Mean
+6004 1303 DS 1 ROI Standard Deviation
+6004 1500 LO 1 Overlay Label
+6004 3000 OW 1 Overlay Data
+6004 4000 LT 1-n Overlay Comments (RET)
+
+6006 0000 UL 1 Group Length
+6006 0010 US 1 Rows
+6006 0011 US 1 Columns
+6006 0012 US 1 Planes
+6006 0015 IS 1 Number of Frames in Overlay
+6006 0022 LO 1 Overlay Description
+6006 0040 CS 1 Overlay Type
+6006 0045 LO 1 Overlay Subtype
+6006 0050 SS 2 Overlay Origin
+6006 0051 US 1 Image Frame Origin
+6006 0052 US 1 Overlay Plane Origin
+6006 0060 LT 1 Overlay Compression Code (RET)
+6006 0100 US 1 Overlay Bits Allocated
+6006 0102 US 1 Overlay Bit Position
+6006 0110 LT 1 Overlay Format (RET)
+6006 0200 US 1 Overlay Location (RET)
+6006 1001 US 1 Overlay Activation Layer
+6006 1100 US 1 Overlay Descriptor - Gray (RET)
+6006 1101 US 1 Overlay Descriptor - Red (RET)
+6006 1102 US 1 Overlay Descriptor - Green (RET)
+6006 1103 US 1 Overlay Descriptor - Blue (RET)
+6006 1200 US 1-n Overlays - Gray
+6006 1201 US 1-n Overlays - Red
+6006 1202 US 1-n Overlays - Green
+6006 1203 US 1-n Overlays - Blue
+6006 1301 IS 1 ROI Area
+6006 1302 DS 1 ROI Mean
+6006 1303 DS 1 ROI Standard Deviation
+6006 1500 LO 1 Overlay Label
+6006 3000 OW 1 Overlay Data
+6006 4000 LT 1-n Overlay Comments (RET)
+
+6008 0000 UL 1 Group Length
+6008 0010 US 1 Rows
+6008 0011 US 1 Columns
+6008 0012 US 1 Planes
+6008 0015 IS 1 Number of Frames in Overlay
+6008 0022 LO 1 Overlay Description
+6008 0040 CS 1 Overlay Type
+6008 0045 LO 1 Overlay Subtype
+6008 0050 SS 2 Overlay Origin
+6008 0051 US 1 Image Frame Origin
+6008 0052 US 1 Overlay Plane Origin
+6008 0060 LT 1 Overlay Compression Code (RET)
+6008 0100 US 1 Overlay Bits Allocated
+6008 0102 US 1 Overlay Bit Position
+6008 0110 LT 1 Overlay Format (RET)
+6008 0200 US 1 Overlay Location (RET)
+6008 1001 US 1 Overlay Activation Layer
+6008 1100 US 1 Overlay Descriptor - Gray (RET)
+6008 1101 US 1 Overlay Descriptor - Red (RET)
+6008 1102 US 1 Overlay Descriptor - Green (RET)
+6008 1103 US 1 Overlay Descriptor - Blue (RET)
+6008 1200 US 1-n Overlays - Gray
+6008 1201 US 1-n Overlays - Red
+6008 1202 US 1-n Overlays - Green
+6008 1203 US 1-n Overlays - Blue
+6008 1301 IS 1 ROI Area
+6008 1302 DS 1 ROI Mean
+6008 1303 DS 1 ROI Standard Deviation
+6008 1500 LO 1 Overlay Label
+6008 3000 OW 1 Overlay Data
+6008 4000 LT 1-n Overlay Comments (RET)
+
+600a 0000 UL 1 Group Length
+600a 0010 US 1 Rows
+600a 0011 US 1 Columns
+600a 0012 US 1 Planes
+600a 0015 IS 1 Number of Frames in Overlay
+600a 0022 LO 1 Overlay Description
+600a 0040 CS 1 Overlay Type
+600a 0045 LO 1 Overlay Subtype
+600a 0050 SS 2 Overlay Origin
+600a 0051 US 1 Image Frame Origin
+600a 0052 US 1 Overlay Plane Origin
+600a 0060 LT 1 Overlay Compression Code (RET)
+600a 0100 US 1 Overlay Bits Allocated
+600a 0102 US 1 Overlay Bit Position
+600a 0110 LT 1 Overlay Format (RET)
+600a 0200 US 1 Overlay Location (RET)
+600a 1001 US 1 Overlay Activation Layer
+600a 1100 US 1 Overlay Descriptor - Gray (RET)
+600a 1101 US 1 Overlay Descriptor - Red (RET)
+600a 1102 US 1 Overlay Descriptor - Green (RET)
+600a 1103 US 1 Overlay Descriptor - Blue (RET)
+600a 1200 US 1-n Overlays - Gray
+600a 1201 US 1-n Overlays - Red
+600a 1202 US 1-n Overlays - Green
+600a 1203 US 1-n Overlays - Blue
+600a 1301 IS 1 ROI Area
+600a 1302 DS 1 ROI Mean
+600a 1303 DS 1 ROI Standard Deviation
+600a 1500 LO 1 Overlay Label
+600a 3000 OW 1 Overlay Data
+600a 4000 LT 1-n Overlay Comments (RET)
+
+600c 0000 UL 1 Group Length
+600c 0010 US 1 Rows
+600c 0011 US 1 Columns
+600c 0012 US 1 Planes
+600c 0015 IS 1 Number of Frames in Overlay
+600c 0022 LO 1 Overlay Description
+600c 0040 CS 1 Overlay Type
+600c 0045 LO 1 Overlay Subtype
+600c 0050 SS 2 Overlay Origin
+600c 0051 US 1 Image Frame Origin
+600c 0052 US 1 Overlay Plane Origin
+600c 0060 LT 1 Overlay Compression Code (RET)
+600c 0100 US 1 Overlay Bits Allocated
+600c 0102 US 1 Overlay Bit Position
+600c 0110 LT 1 Overlay Format (RET)
+600c 0200 US 1 Overlay Location (RET)
+600c 1001 US 1 Overlay Activation Layer
+600c 1100 US 1 Overlay Descriptor - Gray (RET)
+600c 1101 US 1 Overlay Descriptor - Red (RET)
+600c 1102 US 1 Overlay Descriptor - Green (RET)
+600c 1103 US 1 Overlay Descriptor - Blue (RET)
+600c 1200 US 1-n Overlays - Gray
+600c 1201 US 1-n Overlays - Red
+600c 1202 US 1-n Overlays - Green
+600c 1203 US 1-n Overlays - Blue
+600c 1301 IS 1 ROI Area
+600c 1302 DS 1 ROI Mean
+600c 1303 DS 1 ROI Standard Deviation
+600c 1500 LO 1 Overlay Label
+600c 3000 OW 1 Overlay Data
+600c 4000 LT 1-n Overlay Comments (RET)
+
+600e 0000 UL 1 Group Length
+600e 0010 US 1 Rows
+600e 0011 US 1 Columns
+600e 0012 US 1 Planes
+600e 0015 IS 1 Number of Frames in Overlay
+600e 0022 LO 1 Overlay Description
+600e 0040 CS 1 Overlay Type
+600e 0045 LO 1 Overlay Subtype
+600e 0050 SS 2 Overlay Origin
+600e 0051 US 1 Image Frame Origin
+600e 0052 US 1 Overlay Plane Origin
+600e 0060 LT 1 Overlay Compression Code (RET)
+600e 0100 US 1 Overlay Bits Allocated
+600e 0102 US 1 Overlay Bit Position
+600e 0110 LT 1 Overlay Format (RET)
+600e 0200 US 1 Overlay Location (RET)
+600e 1001 US 1 Overlay Activation Layer
+600e 1100 US 1 Overlay Descriptor - Gray (RET)
+600e 1101 US 1 Overlay Descriptor - Red (RET)
+600e 1102 US 1 Overlay Descriptor - Green (RET)
+600e 1103 US 1 Overlay Descriptor - Blue (RET)
+600e 1200 US 1-n Overlays - Gray
+600e 1201 US 1-n Overlays - Red
+600e 1202 US 1-n Overlays - Green
+600e 1203 US 1-n Overlays - Blue
+600e 1301 IS 1 ROI Area
+600e 1302 DS 1 ROI Mean
+600e 1303 DS 1 ROI Standard Deviation
+600e 1500 LO 1 Overlay Label
+600e 3000 OW 1 Overlay Data
+600e 4000 LT 1-n Overlay Comments (RET)
+
+7fe0 0000 UL 1 Group Length
+7fe0 0010 OB 1 Pixel Data
+
+fffa fffa SQ 1 Digital Signatures Sequence
+fffc fffc OB 1 Data Set Trailing Padding
+fffe e000 UL 1 Item
+fffe e00d UL 1 Item Delimitation Item
+fffe e0dd UL 1 Sequence Delimitation Item
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/dicomV3PhilipsIntera.dic b/Utilities/ITK/Utilities/gdcm/Dicts/dicomV3PhilipsIntera.dic
new file mode 100644
index 0000000000000000000000000000000000000000..0619d24b5eb4df2f80dec943812a4428b82da5ab
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/dicomV3PhilipsIntera.dic
@@ -0,0 +1,37 @@
+
+2001 0010 LO 1 Private Creator Group 2001
+2001 1001 FL 1 Chemical Shift
+2001 1002 IS 1 Chemical Shift Number MR
+2001 1003 FL 1 Diffusion B-Factor
+2001 1004 CS 1 Diffusion Direction
+2001 1006 CS 1 Image Enhanced
+2001 1007 CS 1 Image Type ED ES
+2001 1008 IS 1 Phase Number
+2001 100a IS 1 Slice Number MR
+2001 100b CS 1 Slice Orientation
+2001 1011 FL 1 Diffusion Echo Time
+2001 1012 CS 1 Dynamic Series
+2001 1013 SL 1 EPI Factor
+2001 1014 SL 1 Number of Echoes
+2001 1015 SS 1 Number of Locations
+2001 1016 SS 1 Number of PC Directions
+2001 1017 SL 1 Number of Phases MR
+2001 1018 SL 1 Number of Slices MR
+2001 1019 CS 1 Partial Matrix Scanned
+2001 101a FL 1-n PC Velocity
+2001 101b FL 1 Prepulse Delay
+2001 101c CS 1 Prepulse Type
+2001 101d IS 1 Reconstruction Number MR
+2001 101f CS 1 Respiration Sync
+2001 1021 CS 1 SPIR
+2001 1022 FL 1 Water Fat Shift
+2001 105f SQ 1 Stack Sequence
+2001 102d SS 1 Number of Stack Slices
+2001 1032 FL 1-n Stack Radial Angle
+2001 1035 SS 1-n Stack Slice Number
+2001 1036 CS 1-n Stack Type
+2001 1060 SL 1 Number of Stacks
+2001 1081 IS 1 Number of Dynamic Scans
+2005 0010 LO 1 Private Creator Group 2005
+2005 1020 SL 1 Number of Chemical Shifts
+2005 10a1 CS 1 Syncra Scan Type
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/dicomVR.dic b/Utilities/ITK/Utilities/gdcm/Dicts/dicomVR.dic
new file mode 100644
index 0000000000000000000000000000000000000000..6a1f2277aa2ddd2f4a3fd0afd7552dcb812a044e
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/dicomVR.dic
@@ -0,0 +1,27 @@
+AE Application Entity;    // At most 16 bytes
+AS Age String;            // Exactly 4 bytes
+AT Attribute Tag;         // 2 16-bit unsigned short integers
+CS Code String;           // At most 16 bytes
+DA Date;                  // Exactly 8 bytes
+DS Decimal String;        // At most 16 bytes
+DT Date Time;             // At most 26 bytes
+FL Floating Point Single; // 32-bit IEEE 754:1985 float
+FD Floating Point Double; // 64-bit IEEE 754:1985 double
+IS Integer String;        // At most 12 bytes
+LO Long String;           // At most 64 chars
+LT Long Text;             // At most 10240 chars
+OB Other Byte String;     // String of bytes (VR independant)
+OW Other Word String;     // String of 16-bit words (VR dependant)
+PN Person Name;           // At most 64 chars
+SH Short String;          // At most 16 chars
+SL Signed Long;           // Exactly 4 bytes
+SQ Sequence of Items;     // Not Applicable
+SS Signed Short;          // Exactly 2 bytes
+ST Short Text;            // At most 1024 chars
+TM Time;                  // At most 16 bytes
+UI Unique Identifier;     // At most 64 bytes
+UL Unsigned Long;         // Exactly 4 bytes
+UN Unknown;               // Any length of bytes
+US Unsigned Short;        // Exactly 2 bytes
+UT Unlimited Text;        // At most 2^32 -1 chars
+
diff --git a/Utilities/ITK/Utilities/gdcm/Dicts/gdcm.dic.in b/Utilities/ITK/Utilities/gdcm/Dicts/gdcm.dic.in
new file mode 100644
index 0000000000000000000000000000000000000000..37ab8acf06649a7af2632518e96644f1e6bc15c9
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/Dicts/gdcm.dic.in
@@ -0,0 +1 @@
+@TEST_DICT_BODY@
diff --git a/Utilities/ITK/Utilities/gdcm/INSTALL b/Utilities/ITK/Utilities/gdcm/INSTALL
new file mode 100644
index 0000000000000000000000000000000000000000..922c4ae000362ac67f4e04d2038f3b6e0d2b94d7
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/INSTALL
@@ -0,0 +1,19 @@
+###################################################
+The installation documentation entry point is Doc/Website/Installation.html
+###################################################
+As of May 2004, cmake has taken over the world^W autotools, therefore
+you'll need to grab a recent version from: http://cmake.org (later than 1.8.3)
+     
+ Then install instruction are:
+ * cvs -d:pserver:anonymous@cvs.creatis.insa-lyon.fr:2402/cvs/public login
+   answer anonymous
+ * cvs -d:pserver:anonymous@cvs.creatis.insa-lyon.fr:2402/cvs/public co gdcm
+ * mkdir gdcmbin
+ * cd gdcmbin
+ * ccmake ../gdcm
+   [select your configuration]
+ * Press 'c' (configure), Press 'g' (generate)
+ * make
+ * make install
+
+
diff --git a/Utilities/ITK/Utilities/gdcm/PACKAGER b/Utilities/ITK/Utilities/gdcm/PACKAGER
new file mode 100644
index 0000000000000000000000000000000000000000..7a8d88da775953c1d80980273d47ec2f3cb846c9
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/PACKAGER
@@ -0,0 +1,140 @@
+Here is the checklist when freezing a version of gdcm:
+
+* First stage, checkings:
+  1/ Un*x:
+    Notation: we here assume you have a cvs tree in GDCMHOME directory.
+    cvs -d:pserver:anonymous@cvs.creatis.insa-lyon.fr:2402/cvs/public login
+    cvs -d:pserver:anonymous@cvs.creatis.insa-lyon.fr:2402/cvs/public co gdcm
+    cd gdcm
+    export GDCMHOME=`pwd`
+    cvs -d:pserver:anonymous@cvs.creatis.insa-lyon.fr:2402/cvs/public co gdcmData
+
+    1a/ check the full compilation is effective:
+       ./autogen.sh --enable-vtk --enable-python --enable-doxygen
+       make
+        
+    1b/ check the python test suite is clean:
+       cd gdcmPython
+       export PYTHONPATH=`pwd`/..
+       ln -s .libs/pygdcm.so _gdcm.so
+       ln -s .libs/vtkgdcmPython.so .
+       python testSuite.py
+
+    1c/ check the setup.py distutil script is operational and then validate
+        its produced packages through the test suite, in all following cases
+       - Direct installation:
+         cd $GDCMHOME
+         python setup.py install --prefix=/tmp
+         cd /tmp/lib/python2.2/site-packages/
+         ln -s $GDCMHOME/gdcmData .
+         export PYTHONPATH=`pwd`
+         cd gdcmPython/
+         python testSuite.py
+         cd $GDCMHOME
+         \rm -fr build /tmp/lib
+       - Binary distribution:
+         cd $GDCMHOME
+         make clean
+            [ or you migth get some complains about the function 
+              PyVTKClass_vtkGdcmReaderNew being multiply defined: this is
+              because of the loose definition of vtkSources in setup.py
+              in which the usage of the glob function will produce a link
+              stage with multiple occurences of vtkGdcmReaderPython.o)].
+         python setup.py bdist --formats=rpm
+         su
+         rpm -Uvh dist/gdcmPython-0.*.i386.rpm
+         cd /usr/lib/python2.2/site-packages/
+         ln -s $GDCMHOME/gdcmData .
+         cd gdcmPython
+         python testSuite.py
+         rpm --erase gdcmPython
+       - Source distribution and then binary distribution (out of build 
+         source distro):
+         cd $GDCMHOME
+         [make clean (see above) ]
+         python setup.py sdist
+         cd /tmp
+         tar zxvf $GDCMHOME/dist/gdcmPython-*.tar.gz
+         cd gdcmPython-*/
+         python setup.py bdist --formats=rpm
+         cd dist
+         As root, repeat above installation with rpm and test.
+         
+  2/ Windoze:
+    Notation: we consider that GDCMHOME is the directory obtained from the
+    following checkout.
+    cvs -d:pserver:anonymous@cvs.creatis.insa-lyon.fr:2402/cvs/public login
+    cvs -d:pserver:anonymous@cvs.creatis.insa-lyon.fr:2402/cvs/public co gdcm
+    cd gdcm
+    cvs -d:pserver:anonymous@cvs.creatis.insa-lyon.fr:2402/cvs/public co gdcmData
+
+    2a/ compile all projects in the gdcm.dsw workspace.
+
+    2b/ set the PYTHONPATH environement variable to the gdcm/gdcmPython
+       directory
+       check the python test suite is clean (python testSuite.py)
+       cd gdcmPython
+       python testSuite.py
+
+    2c/ check the setup.py distutil script is operational and then validate
+        its produced packages through the test suite, in all following cases
+       - Direct installation:
+         cd $(GDCMHOME)
+         python setup.py install --prefix="c:\tmp"
+         cd /tmp/Lib/site-packages/
+         copy $(GDCMDATAHOME) .
+         export PYTHONPATH="c:\tmp\Lib\site-packages"
+         cd gdcmPython/
+         python testSuite.py
+         remove $(GDCMHOME)\build directory
+       - Binary distribution:
+         cd $(GDCMHOME)
+         python setup.py bdist --formats=wininst
+         install $(GDCMHOME)\dist\gdcmPython-xxx.win32-py2.2.exe
+         cd $(PYTHONHOME)\Lib\site-packages\
+         Check out gdcmData
+         cd gdcmPython
+         clean up PYTHONPATH
+         python testSuite.py
+         remove $(GDCMHOME)\build directory
+       - Source distribution and then binary distribution (out of build
+         source distro):
+         cd $(GDCMHOME)
+         python setup.py sdist --formats=zip
+         unzip $(GDCMHOME)\dist\gdcmPython-xxx.zip in TMPHOME directory
+         cd $(TMPHOME)
+         cd gdcmPython-*/
+         python setup.py bdist --formats=wininst
+         As root, repeat above installation with exe and test.
+         
+* Second stage: preparing packaging:
+  - Update the version number in configure.in (AM_INIT_AUTOMAKE)
+  - Update the version number in setup.py (version entry in setup object).
+
+* Third stage: packaging
+  1/ Un*x
+    1a/  Packaging at the C/C++/Python level (i.e. exports both libraries,
+        include files and python package)
+      - Make sure you have a ~/.rpmmacros file containing the line
+            %_topdir <somedirectoryPath>
+        and that <somedirectoryPath> exists and contains the subdirs
+        BUILD, SOURCES, RPMS/i386, SRPMS, SPECS
+      - cd $(GDCMHOME)
+      - ./autogen.sh --enable-vtk --enable-python --enable-doxygen
+      - make release  (generates gdcm-x.y.z.tar.gz)
+      - rpm -ta gdcm-x.y.z.tar.gz
+      - collect the result in <somedirectoryPath>/RPMS/i386/ and
+        <somedirectoryPath>/SRPMS.
+    1b/ Packaging at the python level:
+         cd $(GDCMHOME)
+         python setup.py sdist
+         python setup.py bdist --formats=rpm
+         collect both source distro and binary distro
+
+  2/ Un*x
+    2a/ Packaging at the python level:
+         cd $(GDCMHOME)
+         python setup.py sdist --formats=zip
+         python setup.py bdist --formats=wininst
+         collect both source distro and binary distro
+
diff --git a/Utilities/ITK/Utilities/gdcm/README b/Utilities/ITK/Utilities/gdcm/README
new file mode 100644
index 0000000000000000000000000000000000000000..f4f531397c4cc6d635c5601dd90f4d40ae8df3e2
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/README
@@ -0,0 +1,28 @@
+For a general introduction/features/limitations/requirement please
+refer to http://www.creatis.insa-lyon.fr/Public/Gdcm
+
+Just a quick note on the build process of GDCM. GDCM build process
+make use of the cmake software(*). This allow us:
+1. To get rid of the autoconf/autotools insanity
+2. Transparently generate Unix Makefiles, NMake Makefiles, 
+Borland Makefiles, VS6/7/8 Project, XCode 1.5...
+3. Automatic nightly testing, one of the most important thing
+for a robust library/software devlpt process. GDCM devpt is develop
+based on the XP definition, and to preserve backward compatibility 
+make sure that code is working from one release to another: each night
+we configure, we build and we test GDCM. The result are then send to 
+the dashboard located at:
+
+   http://public.kitware.com/dashboard.php?name=gdcm
+
+A continuous dashboard make also sure that aby commit did not introduce
+any error on another plateform, a warning or broke a test...
+
+Therefore you should be able to use GDCM from the bleeding edge without
+knowing to much on what is going on. All you need to do is have a look
+at the GDCM dashboard, and if your plateform is 'green' then you can 
+update your cvs copy and compile safely knowing that there are very few chances
+that something won't work. Cheers !
+
+
+(*) http://www.cmake.org for more information
diff --git a/Utilities/ITK/Utilities/gdcm/README.ITK.txt b/Utilities/ITK/Utilities/gdcm/README.ITK.txt
new file mode 100644
index 0000000000000000000000000000000000000000..70fb620d41955937cb2648bd97e3bd161ea813cb
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/README.ITK.txt
@@ -0,0 +1,14 @@
+This directory contains a subset of the CREATIS Dicom library
+gdcm version 1.0.  We only include enough of distribution to build
+gdcm.  We do not include the standard executables that come with
+gdcm (PrintHeader, vtkviewer, or any python sample). 
+
+We'd like to thank the Creatis lab for distributing a public GDCM 
+IO library, and modifying the license to be BSD compatible
+                                                                                                                                                             
+Modifications
+-------------
+
+We reuse the jpeg library from ITK instead of building the one shipped
+with gdcm. Therefore all gdcmjpeg* name were changed to itkjpeg*.
+Same thing for include directory
diff --git a/Utilities/ITK/Utilities/gdcm/gdcm.spec.in b/Utilities/ITK/Utilities/gdcm/gdcm.spec.in
new file mode 100644
index 0000000000000000000000000000000000000000..d073f57ef2951c262826be997aa35cc409d5aa5c
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/gdcm.spec.in
@@ -0,0 +1,48 @@
+# Note that this is NOT a relocatable package
+%define  ver       @VERSION@
+%define  RELEASE  1
+%define  rel      %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
+%define prefix    /usr
+
+Summary: Dicom library
+Name: gdcm
+Version: %ver
+Release: %rel
+License: BSD 
+Group: Development/Tools
+URL: http://www.creatis.insa-lyon.fr/Public/Gdcm
+Source0: http://www.creatis.insa-lyon.fr/Public/Gdcm/gdcm-%{version}.tar.gz
+BuildRoot: %{_tmppath}/gdcm-root
+Requires: python2
+BuildRequires: doxygen, swig13, python2
+Packager: Fabrice Bellet <Fabrice.Bellet@creatis.insa-lyon.fr>
+
+%description
+gdcm is a library dedicated to read and write DICOM files.
+
+%prep
+%setup -q 
+
+%build
+%configure --enable-doxygen --enable-python
+make
+
+%install
+%makeinstall 
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc AUTHORS INSTALL NEWS README TODO
+%{_libdir}/libgdcm*
+%{_datadir}/gdcm
+%{_libdir}/python*/site-packages/gdcm
+%{_includedir}/*.h
+
+%changelog
+* Mon Mar 17 2003 Fabrice Bellet <Fabrice.Bellet@creatis.insa-lyon.fr> 0.1.0-1
+- Rebuild for Red Hat Linux 7.3
+- First packaging.
+
diff --git a/Utilities/ITK/Utilities/gdcm/gdcmConfigure.h.in b/Utilities/ITK/Utilities/gdcm/gdcmConfigure.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..806d5ae4b3835dec1706c88a00e3e1590efbe28d
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/gdcmConfigure.h.in
@@ -0,0 +1,98 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmConfigure.h.in,v $
+  Language:  C++
+  Date:      $Date: 2006/02/27 23:11:35 $
+  Version:   $Revision: 1.8 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef __gdcmConfigure_h
+#define __gdcmConfigure_h
+
+/* This header is configured by GDCM's build process.  */
+
+/*--------------------------------------------------------------------------*/
+/* Platform Features                                                        */
+
+/* Byte order.  */
+#cmakedefine GDCM_WORDS_BIGENDIAN
+
+/* Allow access to UINT32_MAX , cf gdcmCommon.h */
+#define __STDC_LIMIT_MACROS
+
+/* Hard code the path to the public dictionary */
+#define PUB_DICT_PATH "@GDCM_PUB_DICT_PATH@"
+
+/* Hardcode the path to GDCM_DATA_ROOT */
+#define GDCM_DATA_ROOT "@GDCM_DATA_ROOT@"
+
+/* Usefull in particular for loadshared where the full path
+ * to the lib is needed */
+#define GDCM_EXECUTABLE_OUTPUT_PATH "@EXECUTABLE_OUTPUT_PATH@"
+#define GDCM_LIBRARY_OUTPUT_PATH    "@LIBRARY_OUTPUT_PATH@"
+
+/* For older gcc / broken plateform */
+#cmakedefine GDCM_NO_ANSI_STRING_STREAM
+
+/* I guess something important */
+#cmakedefine CMAKE_HAVE_STDINT_H
+#cmakedefine CMAKE_HAVE_INTTYPES_H
+
+/* This variable allows you to have helpful debug statement */
+/* That are in between #ifdef / endif in the gdcm code */
+/* That means if GDCM_DEBUG is OFF there shouldn't be any 'cout' at all ! */
+/* only cerr, for instance 'invalid file' will be allowed */
+#cmakedefine GDCM_DEBUG
+
+/* Whether we are building shared libraries.  */
+/* This was important as long as GDCM is LGPL */
+#cmakedefine BUILD_SHARED_LIBS
+
+/* GDCM uses __FUNCTION__ which is not ANSI C, but C99 */
+#cmakedefine GDCM_COMPILER_HAS_FUNCTION
+
+
+/* GetMacAddress require a lot of include file to access low level API */
+#cmakedefine CMAKE_HAVE_UNISTD_H
+#cmakedefine CMAKE_HAVE_STDLIB_H
+#cmakedefine CMAKE_HAVE_SYS_IOCTL_H
+#cmakedefine CMAKE_HAVE_SYS_SOCKET_H
+#cmakedefine CMAKE_HAVE_SYS_SOCKIO_H
+#cmakedefine CMAKE_HAVE_NET_IF_H
+#cmakedefine CMAKE_HAVE_NETINET_IN_H
+#cmakedefine CMAKE_HAVE_NET_IF_DL_H
+#cmakedefine CMAKE_HAVE_NET_IF_ARP_H
+#cmakedefine HAVE_SA_LEN
+
+#cmakedefine GDCM_FORCE_BIGENDIAN_EMULATION
+
+/* For OpenJPEG */
+#cmakedefine OPJ_EXPORTS
+#cmakedefine OPJ_STATIC
+
+/*--------------------------------------------------------------------------*/
+/* GDCM Versioning                                                          */
+
+/* Version number.  */
+#define GDCM_MAJOR_VERSION @GDCM_MAJOR_VERSION@
+#define GDCM_MINOR_VERSION @GDCM_MINOR_VERSION@
+#define GDCM_BUILD_VERSION @GDCM_BUILD_VERSION@
+#define GDCM_VERSION "@GDCM_VERSION@"
+
+/*--------------------------------------------------------------------------*/
+/* GDCM deprecation mechanism                                               */
+#cmakedefine GDCM_LEGACY_REMOVE
+#cmakedefine GDCM_LEGACY_SILENT
+
+
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/.cvsignore b/Utilities/ITK/Utilities/gdcm/src/.cvsignore
new file mode 100644
index 0000000000000000000000000000000000000000..30a9615f03da8e36010d2db36e371fde5de29912
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/.cvsignore
@@ -0,0 +1,18 @@
+*.o
+*.so
+.deps
+.libs
+Makefile.in
+Makefile
+*.lo
+*.la
+*Debug*
+*Release*
+config.h
+config.h.in
+stamp-h
+stamp-h1
+stamp-h.in
+DartTestfile.txt
+cmake.check_depends
+cmake.depends
diff --git a/Utilities/ITK/Utilities/gdcm/src/CMakeLists.txt b/Utilities/ITK/Utilities/gdcm/src/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f7e967c483893ed704fd7674821c88f478723c2f
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/CMakeLists.txt
@@ -0,0 +1,83 @@
+#-----------------------------------------------------------------------------
+# Rebuild gdcm whenever a file starting with gdcm* is modified
+INCLUDE_REGULAR_EXPRESSION("^gdcm.*$")
+
+# Add proper includes
+INCLUDE_DIRECTORIES(
+  ${GDCM_SOURCE_DIR}/src
+  ${GDCM_BINARY_DIR} #for gdcmConfigure.h
+  ${GDCM_BINARY_DIR}/src #for gdcmjpeg 8, 12 and 16 
+)
+
+SET(libgdcm_la_SOURCES
+   gdcmArgMgr.cxx
+   gdcmBase.cxx
+   gdcmBinEntry.cxx
+   gdcmContentEntry.cxx
+   gdcmDebug.cxx
+   gdcmDicomDir.cxx
+   gdcmDicomDirElement.cxx
+   gdcmDicomDirImage.cxx
+   gdcmDicomDirMeta.cxx
+   gdcmDicomDirObject.cxx
+   gdcmDicomDirPatient.cxx
+   gdcmDicomDirVisit.cxx
+   gdcmDicomDirSerie.cxx
+   gdcmDicomDirStudy.cxx
+   gdcmDict.cxx
+   gdcmDictEntry.cxx
+   gdcmDictGroupName.cxx
+   gdcmDictSet.cxx
+   gdcmDirList.cxx
+   gdcmDocEntry.cxx
+   gdcmDocEntryArchive.cxx
+   gdcmDocEntrySet.cxx
+   gdcmDocument.cxx
+   gdcmElementSet.cxx
+   gdcmException.cxx
+   gdcmFileHelper.cxx
+   gdcmGlobal.cxx
+   gdcmFile.cxx
+   gdcmJPEGFragment.cxx
+   gdcmJPEGFragmentsInfo.cxx
+   gdcmJpeg8.cxx
+   gdcmJpeg12.cxx
+   gdcmJpeg16.cxx
+   gdcmJpeg2000.cxx
+   gdcmOrientation.cxx
+   gdcmPixelReadConvert.cxx
+   gdcmPixelWriteConvert.cxx
+   gdcmRLEFrame.cxx
+   gdcmRLEFramesInfo.cxx
+   gdcmSeqEntry.cxx
+   gdcmSerieHelper.cxx
+   gdcmSQItem.cxx
+   gdcmTS.cxx
+   gdcmUtil.cxx
+   gdcmValEntry.cxx   
+   gdcmValidator.cxx
+   gdcmVR.cxx
+   ${GDCM_BINARY_DIR}/src/gdcmDefaultDicts.cxx
+   )
+
+ADD_LIBRARY(itkgdcm ${libgdcm_la_SOURCES})
+TARGET_LINK_LIBRARIES(itkgdcm 
+  itkjpeg8 
+  itkjpeg12
+  itkjpeg16
+  itkopenjpeg
+)
+IF(WIN32)
+  IF(NOT BORLAND)
+    TARGET_LINK_LIBRARIES(itkgdcm wsock32 snmpapi)
+  ENDIF(NOT BORLAND)
+ENDIF(WIN32)
+
+# Need nsl to resolve gethostbyname on SunOS-5.8
+# and socket also
+IF(CMAKE_SYSTEM MATCHES "SunOS.*")
+  TARGET_LINK_LIBRARIES(itkgdcm socket nsl)
+ENDIF(CMAKE_SYSTEM MATCHES "SunOS.*")
+
+INSTALL_FILES(/include/InsightToolkit/gdcm/src "\\.h$")
+INSTALL_TARGETS(/lib/InsightToolkit itkgdcm)
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcm.h b/Utilities/ITK/Utilities/gdcm/src/gdcm.h
new file mode 100644
index 0000000000000000000000000000000000000000..8d30d2d130f08cbf3cefafa312c0b84e877a015a
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcm.h
@@ -0,0 +1,45 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcm.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCM_H
+#define GDCM_H
+
+// General purpose include file. This file should be included by
+// external users of gdcm. It exposes the necessary API.
+
+#include "gdcmCommon.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+
+#include "gdcmDictEntry.h"
+#include "gdcmDict.h"
+#include "gdcmDictSet.h"
+
+#include "gdcmDocument.h"
+#include "gdcmFile.h"
+
+#include "gdcmFileHelper.h"
+#include "gdcmSerieHelper.h"
+
+#include "gdcmValEntry.h"
+#include "gdcmBinEntry.h"
+#include "gdcmSeqEntry.h"
+
+#include "gdcmValidator.h"
+
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmArgMgr.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmArgMgr.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..25bf79579ef8dd6fc730da3848b4502e6709f0fc
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmArgMgr.cxx
@@ -0,0 +1,906 @@
+/*=========================================================================
+  
+  Program:   gdcm
+  Module:    $RCSfile: gdcmArgMgr.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.2 $
+  
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+  
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+  
+=========================================================================*/
+
+#include <stdio.h>
+#include <iostream>
+#include <ctype.h>
+#include <string.h>  // For strlen
+
+// No strcasecmp in WIN32 world, but stricmp
+// http://www.opengroup.org/onlinepubs/007908799/xsh/strcasecmp.html
+#ifdef _WIN32
+#define strcasecmp stricmp
+#endif
+
+#include <string.h>  // For strtok and strlen
+#include <stdlib.h>  // For strtol and strtod
+
+#include "gdcmArgMgr.h"
+
+namespace gdcm 
+{
+//-------------------------------------------------------------------------
+// Constructor / Destructor
+
+/**
+ * \brief   constructor
+ * @param argc arguments count, as passed to main()
+ * @param argv  pointers array on the arguments passed to main()  
+ */
+ ArgMgr::ArgMgr(int argc, char **argv)
+ {
+   int i;
+   int nblettre;
+   ArgUsed = NULL;
+   Appel   = NULL;
+  
+   /* Read the parameters of the command line *************************/
+   for ( ArgCount=0, nblettre=1 , i=0; i<argc; i++) 
+   {
+      if ( FiltreLong(argv[i]) ) 
+      { 
+          std::cout << "Argument too long ( > "
+                    << ARG_LONG_MAX << ")" << std::endl;
+          return;
+      }
+      if ( argv[i][0] == '@' )
+      {                       
+         nblettre  += ArgLoadFromFile ( &argv[i][1] );   
+      }
+      else
+      {                                         
+         ArgLab [ArgCount] = strcpy ( (char *)malloc(strlen(argv[i])+1), argv[i] ) ;
+         nblettre  += 1 + strlen(ArgLab[ArgCount]);     
+         ArgCount++;                               
+      }
+      if (ArgCount >= ARGMAXCOUNT )      
+      {
+          std::cout << "Too many Arguments ( more than "
+                    << ARGMAXCOUNT << ")" << std::endl; 
+          return;
+      }
+   }
+
+   /* Fills an array with the already used parameters ****/
+   ArgUsed = (char *)calloc (1, ArgCount );
+
+   /* Builds the full string with all the parameters  **************/
+   Appel = (char *) calloc (1, nblettre );
+
+   for ( *Appel = '\0', i=0; i<ArgCount; i++)
+   {
+      strcat ( Appel, ArgLab [i] ) ;
+      strcat ( Appel, " " ) ;
+   }
+
+   /* Splitting label from label value *************************************/
+   for ( i=0; i<ArgCount; i++) 
+   {
+      char * egaloufin = ArgLab[i] ;
+      while ( (*egaloufin != '\0') && (*egaloufin != '=') ) 
+         egaloufin ++ ;
+      if ( *egaloufin ) *(egaloufin++) = '\0';
+      ArgStr[i]= egaloufin;
+   }
+
+   /* Set labels to upper-case (labels are not case sensitive ) *********/
+   for ( i=0; i<ArgCount; i++)
+      ArgLab[i] = Majuscule ( ArgLab[i] ) ;
+
+  /* Standard arguments are managed by ArgStdArgs **********************/
+   ArgStdArgs(); 
+ }
+
+/**
+ * \brief  canonical destructor
+ */
+ArgMgr::~ArgMgr()
+{
+   for(int i=0;i<ArgCount;i++)
+      if ( ArgLab[i] )
+         free(ArgLab[i]);
+   if ( ArgUsed )
+      free(ArgUsed);
+   if ( Appel )
+      free(Appel);
+}
+ 
+/**
+ * \brief  checks if a parameter exists in the command line
+ * @param param  label name
+ * @return   0 if label is not found
+ *           else, returns the number of the spot it was found last time.
+ */
+int ArgMgr::ArgMgrDefined( const char *param )
+{
+  int i;
+  bool trouve;
+  char *temp;
+  temp = Majuscule ( param ) ;
+  for ( i = ArgCount-1; i>0; i-- )
+  { 
+    trouve = ( strcmp( ArgLab[i], temp )==0 ) ;
+    if ( trouve )
+    {
+      ArgUsed[i] = true ;           
+      for ( int j=1; j<i; j++)
+      {                     
+         if ( (!ArgUsed[j])&&(!strcmp(ArgLab[i],ArgLab[j])) )
+            ArgUsed[j] = i ;
+      }
+      return i ;
+    }
+  }
+  return 0 ;
+}
+
+/**
+ * \brief  Gets the parameter value, read on the command line
+ * @param param   name of the searched parameter label
+ * @return   Value, as a char array, of the parameter
+ *            whose label is given.
+ */
+char *ArgMgr::ArgMgrValue ( const char *param )
+{
+   int trouve ;
+   if ( (trouve = ArgMgrDefined ( param )) != false )
+      return ArgStr[trouve] ;
+   else
+      return NULL ;
+}
+
+/**
+ * \brief  Search for the first not yet used label
+ * @return Pointer to the char array holding the first non used label
+ */
+const char *ArgMgr::ArgMgrUnused ( )
+{
+   int i ;
+   for ( i=ArgCount-1; i>0; i-- )
+   {
+      if ( ! ArgUsed[i] )
+      {
+         ArgMgrDefined(ArgLab[i]);
+         return ArgLab[i] ;
+      }
+  }
+  return NULL ;
+}
+
+/**
+ * \brief  Prints unused labels, if any
+ * @return number of unused labels
+ */
+int ArgMgr::ArgMgrPrintUnusedLabels ()
+{
+   const char *label;
+   int i=0;
+   while ( (label=ArgMgrUnused())!=0 )
+   {
+      if (i==0)
+         std::cout << "\n Unused Labels:" << std::endl
+                   << "=============="    << std::endl;
+      std::cout << "Label : " << label << " = " 
+                << ArgMgrValue(label) << std::endl;
+      i++;
+   }
+   return i;
+}
+
+/**
+ * \brief  Prints program usage
+ * @param usage  array of pointers to the documentation lines of the program.
+ * @return exception code
+ */
+int ArgMgr::ArgMgrUsage(const char **usage )
+{
+   while ( *usage ) 
+      std::cout << std::endl << *(usage++);
+   std::cout << std::endl; 
+   return (0);
+}
+
+/**
+ * \brief Forget it, right now ... 
+ * Saves a char. array in a parameter file
+ *         whose name is given on command line by : PARAMOUT=???
+ *         or, as a default, by ARG_DEFAULT_PARAMOUT
+ * @param param  char. array that defines the parameter
+ * @return   Entier correspondant au rang dans la liste de labels
+ */
+int ArgMgr::ArgMgrSave ( const char *param )
+{
+   static int   deja = 0;
+   FILE         *fd;
+   if ( *ArgParamOut == '\0' )
+      return 0;
+   if ( deja ) 
+   {
+      fd = fopen ( ArgParamOut, "a+" );
+   }
+   else
+   {
+      deja = 1;
+      fd = fopen ( ArgParamOut, "w" );
+   } 
+   if ( !fd ) 
+      return 0;
+   fprintf ( fd, "%s\n", param );
+   fclose  ( fd );
+   return 1;
+}
+
+/**
+ * \brief  Gets an int value passed as an argument to a program
+ *         (use default value if not found)
+ *         EXAMPLE:     int dimx = ArgMgrGetInt ( "DIMX", 256 );
+ * @param label   label name 
+ * @param defaultVal default value
+ * @return parameter value
+ */
+int ArgMgr::ArgMgrGetInt(const char *label, int defaultVal)
+{
+   return ( (ArgMgrDefined(label))
+            ? (atoi(ArgMgrValue(label)))
+            : (defaultVal) );
+}
+
+/**
+ * \brief  Gets a float value passed as an argument to a program
+ *         (use default value if not found)
+ *         EXAMPLE:     float scale = ArgMgrGetFloat ( "SCALE", 0.33 );
+ * @param param   label name 
+ * @param defaultVal default value
+ * @return parameter value
+ */
+float ArgMgr::ArgMgrGetFloat(const char *param, float defaultVal)
+{
+   return     ( (ArgMgrDefined(param))
+               ? ((float)atof(ArgMgrValue(param)))
+               : (defaultVal) );
+}
+
+/**
+ * \brief  Gets a 'string' value passed as an argument to a program
+ *         (use default value if not found)
+ *         EXAMPLE :  char *imageName = ArgMgrGetString( "NAME", "test.dcm" );
+ * @param param   label name 
+ * @param defaultVal default value
+ * @return parameter value
+ */
+const char *ArgMgr::ArgMgrGetString(const char *param, const char *defaultVal)
+{
+   return    ( (ArgMgrDefined(param)) 
+              ? (ArgMgrValue(param))
+              : (defaultVal) );
+}
+
+/**
+ * \brief  Gets a value amongst a set of values
+ *         (use default value if not found) 
+ *         EXAMPLE:     int nlab = ArgMgrGetLabel("CONFIRM","NO\\YES", 0); 
+ * @param param   label name 
+ * @param liste  character Chain describing the various values.
+ *               Value are separated by '\\'.
+ *               Not case sensitive.
+ * @param val  number of default value
+ * @return   int : range of value amongst the values list
+ */
+int ArgMgr::ArgMgrGetLabel (const char *param, const char *liste, int val )
+{
+  char *lab;
+  const char *vallab;
+  int i = 1;
+  char *tmp;
+  tmp = (char *) malloc(strlen(liste)+1);
+  strcpy(tmp,liste);
+
+  if ( (vallab = ArgMgrGetString(param,(const char *)NULL)) != 0 ) 
+  { 
+     for ( lab = strtok (tmp,"\\"); 
+           lab != 0; 
+           lab = strtok(0L,"\\"), i++ )
+     { 
+        // strcmp ignoring case
+        if( strcasecmp(lab, vallab) == 0)
+           return i;
+     } 
+     val=0;
+   }
+   free(tmp);
+   return val;
+}
+
+/**
+ * \brief  Demands a value amongst a set of values (abort if not found)
+ *         EXaMPLE:     int nlab = ArgMgrWantLabel("CONFIRM","NO\\YES", usage); 
+ * @param param   label name 
+ * @param liste  character Chain describing the various values.
+ *               Labels are separated by  '\\'.
+ *               No case sensitive.
+ *               WARNING this will be changed (not const)
+ * @param usage Usage program (displayed if label not found)
+ * @return   int : range of value amongst the values list
+ */
+int ArgMgr::ArgMgrWantLabel (const char *param, char *liste, const char **usage )
+{
+   char *lab;
+   const char *vallab;
+   int i = 1;
+   if ( (vallab = ArgMgrGetString(param,0)) != 0 ) 
+   {
+      for ( lab = strtok (liste,"\\"); lab != 0; lab = strtok(0L,"\\"), i++ )
+        if ( strcasecmp(lab,vallab)==0) 
+           return i;
+      return 0;
+   }
+   ArgMgrUsage(usage);
+   return 0;
+}
+
+/**
+ * \brief  Demands an int value passed as an argument to a program
+ *         If not found usage is displayed and the prog aborted
+ *  EXAMPLE:     int dimx = ArgMgrWantInt ( "DIMX", usage );
+ * @param label   label name 
+ * @param usage Usage program (displayed if label not found)
+ * @return parameter value
+ */
+int ArgMgr::ArgMgrWantInt (const char *label, const char **usage)
+{
+   return        ( (ArgMgrDefined(label) ) 
+                 ? (atoi(ArgMgrValue(label) ) ) 
+                 : (ArgMgrUsage(usage),1) );
+}
+
+/**
+ * \brief  Demands a float value passed as an argument to a program
+ *         If not found usage is displayed and the prog aborted
+ *  EXAMPLE:     float scale = ArgMgrWantFloat ( "SCALE", usage );
+ * @param label   label name 
+ * @param usage Usage program (displayed if label not found)
+ * @return parameter value
+ */
+float ArgMgr::ArgMgrWantFloat (const char *label, const char **usage)
+{
+   return       ( (ArgMgrDefined(label) ) 
+                ? ((float)atof(ArgMgrValue(label) ) ) 
+                : (ArgMgrUsage(usage),(float)1.0) );
+}
+
+/**
+ * \brief  Demands a 'string' value passed as an argument to a program
+ *         If not found usage is displayed and the prog aborted
+ *  EXAMPLE:     char *code = ArgMgrWantString ( "CODE", usage );
+ * @param label   Parameter label
+ * @param usage Usage program (displayed if label not found)
+ * @return parameter value
+ */
+char *ArgMgr::ArgMgrWantString(const char *label, const char **usage)
+{
+   return      ( (ArgMgrDefined(label) ) 
+               ? (ArgMgrValue(label) ) 
+               : (ArgMgrUsage(usage),(char*)0) );
+}
+
+/**
+ * \brief  decodes and returns an array of 'STRING'
+ *  EXAMPLE:     char **codes = ArgMgrGetListOfString ( "CODES", &nbOfCodes ); 
+ * @param label   label name 
+ * @param number  nb of found 'STRINGs'
+ * @return   Pointer to the 'STRING' array; NULL if error
+ */
+char **ArgMgr::ArgMgrGetListOfString ( const char *label, int *number )
+{
+  int taille;
+  char  *value = ArgMgrValue(label);
+  char **liste;
+  char **elem;
+  char  *chainecur; 
+  if (!value)
+  {
+     *number = 0;
+     return 0;
+  }
+  *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
+  taille = *number;
+  liste = (char **) malloc (sizeof(char*) * taille + strlen(value)+1);
+  if ( !liste )
+     return 0;
+  value = strcpy( ((char*)liste)+sizeof(char*) * taille, value );
+  for ( elem = liste, chainecur = strtok(value,", ");
+        taille>0;
+        taille--, chainecur = (chainecur) ? strtok ( 0, ", " ) : 0 )
+  {
+    *(elem++) = chainecur;
+  }
+  return liste;
+}
+
+/**
+ * \brief  decodes and returns an array of 'INT'
+ *  EXAMPLE:     int *points = ArgMgrGetListOfInt ( "POINTS", &nbOfPoints );  
+ * @param label   label name 
+ * @param number  nb of found INT
+ * @return   Pointer to the INT array; NULL if error
+ */
+int *ArgMgr::ArgMgrGetListOfInt ( const char *label, int *number )
+{
+  char *value = ArgMgrValue(label);
+  int *liste;
+  int *elem;
+  int taille;
+  if (!value)
+  {
+     *number = 0;
+     return 0;
+  }
+  *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
+  taille= *number;
+  liste = (int *) calloc (1,sizeof(int)*taille );
+  if ( !liste )
+     return 0;
+  elem = liste;
+  //*number = 1;
+
+  while ( taille>0 ) 
+  {
+    *(elem++) = (int) strtol ( value, &value, 10 );      
+    if ( *value == '\0' )
+       return liste;
+    if ( *(value++) != ',' ) 
+    {
+      free (liste);
+      return 0;
+    }
+    taille --;
+  }
+return liste;
+}
+
+/**
+ * \brief  decodes and returns an array of 'FLOAT'
+ * @param label   label name 
+ * @param number  number of found FLOATs
+ * @return   Pointer to the FLOAT array; NULL if error
+ */
+float *ArgMgr::ArgMgrGetListOfFloat ( const char *label, int *number )
+{
+  char *value = ArgMgrValue(label);
+  float *liste;
+  float *elem;
+  int taille;
+  if (!value)
+    return 0;
+  *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
+  taille= *number;
+  liste = (float *) calloc (1,sizeof(float)*taille );
+  if ( !liste )
+  {
+     *number = 0;
+     return 0;
+  }
+  elem = liste;
+  //*number = 1;
+
+  while ( taille>0 ) 
+  {
+    *(elem++) = (float) strtod ( value, &value );      
+    if ( *value == '\0' )
+       return liste;
+    if ( *(value++) != ',' )
+    {
+      free (liste);
+      return 0;
+    }
+    taille --;
+  }
+return liste;
+}
+
+/**
+ * \brief  decodes and returns an array of 'INT pairs', passed in decimal
+ * @param param   label name 
+ * @param number   nb of found pairs
+ * @return        pointer to the array of 'INT pairs'; NULL if fail
+ */
+int *ArgMgr::ArgMgrGetIntEnum ( const char *param, int *number )
+{
+   char *value = ArgMgrValue(param);
+   int *liste;
+   if (!value) 
+   {
+      *number = 0; 
+      return 0;
+   }
+   liste = IdStrIntEnum(value, number);
+   return liste;
+}
+
+/**
+ * \brief  decodes and returns an array of 'INT16 pairs', passed in hexadecimal
+ * @param param   label name 
+ * @param number   nb of found pairs
+ * @return        pointer to the array of 'INT16 pairs'; NULL if fail
+ */
+uint16_t *ArgMgr::ArgMgrGetXInt16Enum ( const char *param, int *number )
+{
+   char *value = ArgMgrValue(param);
+   uint16_t *liste;
+   if (!value) 
+   {
+      *number = 0; 
+      return 0;
+   }
+   liste = IdStrXInt16Enum(value, number);
+   return liste;
+}
+/**
+ * \brief  decodes and returns an array of 'FLOAT pairs'
+ * @param param   label name 
+ * @param number   nb of found pairs
+ * @return        pointer to the array of 'FLOAT pairs'; NULL if fail
+
+ */
+float *ArgMgr::ArgMgrGetFloatEnum ( const char *param, int *number )
+{
+   char  *value = ArgMgrValue(param);
+   float *liste;
+   if (!value) 
+   {
+      *number = 0; 
+      return 0;
+   }
+   liste = IdStrFloatEnum(value, number);
+   return liste;
+}
+
+// ------------------------ Those are 'service functions' ---------------------
+// ------------------------       internal use only       ---------------------
+
+/**
+ * \brief     Counts the nb of occurrences of a given charact within a 'string' 
+ * @param chaine     Pointer to the 'string'
+ * @param caract     charact to count
+ * @return       occurence number
+ */
+int ArgMgr::IdStrCountChar (char *chaine, int caract)
+{
+  int i=0;
+  char *ptr;
+  for ( ptr = chaine ; *ptr!='\0' ; ptr ++ ) 
+     if (*ptr==caract) 
+        i++;  
+  return i;
+}
+
+/**
+ * \brief     returns an array of 'INT pairs'
+ * @param value  char array decribing a set of 'INT pairs' (f1-l1, f2-l2, ...)
+ * @param number nb of found INT pairs
+ * @return       pointer to the array of 'INT pairs'
+ */
+int *ArgMgr::IdStrIntEnum ( char* value, int *number)
+{
+   int* liste;
+   int taille;
+   int i;
+
+   *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
+   taille= *number;
+   liste = (int *) calloc (1,sizeof(int)*2*taille );
+   if ( !liste )
+   {
+      return 0;
+   }
+   i=0;
+   while ( taille>0 ) 
+   {
+      liste[i] = (int) strtol ( value, &value, 10 );
+      if ( *value == '\0' ) 
+      {
+         liste[i+1]=liste[i];
+         return liste;
+      }
+      if ( *(value++) != '-' ) 
+      {
+         liste[i+1]=liste[i];
+         value--;
+       }
+       else
+       {
+          liste[i+1] = (int) strtol ( value, &value, 10 );
+       }
+       if ( *value == '\0' )
+          return liste;
+       if ( *(value++) != ',' )
+       {
+          free (liste);
+          return 0;
+       }
+       taille --; i+=2;
+   }
+   return liste;
+}
+
+/**
+ * \brief     returns an array of set of 'INT16 pairs', passed in Hexadecimal
+ * @param value  char array decribing a set of 'INT16 pairs' (f1-l1, f2-l2, ...)
+ *               coded in hexadecimal e.g. 0x0008,0x00ac
+ * @param number nb of found pairs
+ * @return        array of set of 'INT16 pairs'
+ */
+uint16_t *ArgMgr::IdStrXInt16Enum ( char *value, int *number)
+{
+   uint16_t *liste;
+   int taille;
+   int i;
+
+   *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
+   taille= *number;
+   liste = (uint16_t *) calloc (1,sizeof(uint16_t)*2*taille );
+   if ( !liste )
+   {
+      return 0;
+   }
+   i=0;
+   while ( taille>0 ) 
+   {
+      liste[i] = (uint16_t) strtol ( value, &value, 16 );
+      if ( *value == '\0' ) 
+      {
+         liste[i+1]=liste[i];
+         return liste;
+      }
+      if ( *(value++) != '-' ) 
+      {
+         liste[i+1]=liste[i];
+         value--;
+       }
+       else
+       {
+          liste[i+1] = (uint16_t) strtol ( value, &value, 16 );
+       }
+       if ( *value == '\0' )
+          return liste;
+       if ( *(value++) != ',' )
+       {
+          free (liste);
+          return 0;
+       }
+       taille --; i+=2;
+   }
+   return liste;
+} 
+/**
+ * \brief     returns an array of 'FLOAT pairs'
+ * @param value  char array decribing a set of 'FLOAT pairs' (f1-l1, f2-l2, ...)
+ * @param number nb of found pairs
+ * @return       pointer to the array of 'FLOAT pairs'; NULL if fail
+ */
+float *ArgMgr::IdStrFloatEnum (char *value, int *number)
+{
+   float *liste;
+   int taille;
+   int i;
+   *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
+   taille= *number;
+   liste = (float *) calloc (1,sizeof(float)*2*taille );
+   if ( !liste )
+      return 0;
+   i=0;
+   while ( taille>0 ) 
+   {
+      liste[i] = (float) strtod ( value, &value );      
+      if ( *value == '\0' ) 
+      {
+         liste[i+1]=liste[i];
+         return liste;
+      }
+      if ( *(value++) != '-' ) 
+      {
+         liste[i+1]=liste[i];
+         value--;
+      }
+      else
+      {
+          liste[i+1] = (float) strtod ( value, &value );
+      }
+      if ( *value == '\0' ) 
+         return liste;
+      if ( *(value++) != ',' )
+      {
+         free (liste);
+         return 0;
+      }
+      taille --; i+=2;
+   }
+   return liste;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+/**************************************************************************
+*                                                                         *
+* Nom de la fonction : Majuscule                                          *
+* Role ............. : Creates a new Upper case char array.               *
+* parameters ....... : Pointer to the initial char array.                 *                           *
+* Valeur retournee . : Pointer to the new Upper case char array.          *
+*                                                                         *
+**************************************************************************/
+char *ArgMgr::Majuscule (const char *chaine )
+{
+  char *ptr, *ptr2, *ptr3;
+  ptr2 = (char *)malloc(strlen(chaine)*sizeof(char)+1);
+  ptr3=ptr2;
+  for ( ptr = (char *)chaine ; *ptr!='\0' ; ptr ++ ) 
+   {  
+       *ptr3 = toupper ( * ptr ); ptr3++; 
+   }
+  *ptr3='\0'; 
+  return ptr2;
+}
+
+/**************************************************************************
+*                                                                         *
+* Nom de la fonction : FiltreLong                                         *
+* Role ............. : Stops the program if argument is too long.         *
+*                      ARG_LONG_MAX defines max length.                   *
+* parameters ....... : Pointer to the argument.                           *
+* Valeur retournee . : false if OK.                                       *
+*                      true if KO.                                        *
+**************************************************************************/
+int ArgMgr::FiltreLong ( const char *arg  )
+{
+  int  n = 0 ;
+  while ( (n++<ARG_LONG_MAX) && (*(arg++) != '\0') ) ;
+  return (n>=ARG_LONG_MAX) ;
+}
+
+/*------------------------------------------------------------------------
+ | Role       : Reads a parameter from a file
+ | Return     : Type   : char *
+ |              Role   : pointer to the label
+ | parameters : param  : char *
+ |              Role   : one where the parameter will be stored
+ |              fd     : FILE *
+ |              Role   : File description (assumed to be open)
+ +------------------------------------------------------------------------*/
+const char *ArgMgr::LoadedParam ( const char *param, FILE *fd )
+{
+  int    carlu;
+  char  *car = (char *)param;
+  int    quote = false;
+  int    nbcar = 0;
+
+  /* remove spaces at the beginning****/
+  while ( isspace(carlu=fgetc (fd)) );
+  if (carlu==EOF)
+     return 0;
+  /* Search for a " */
+  if ( carlu=='\"' ) 
+  {
+    carlu=fgetc(fd);
+    quote=true;
+  /* Read all the characters */
+  }
+  while (  (carlu!=EOF)
+        && (  ( (!quote)&&(!isspace(carlu)) )
+         ||( (quote)&& !(carlu=='\"')   ) ) ) 
+  {
+     *(car++) = (char) carlu;
+     nbcar ++;
+  /* sans depasser la taille max*/
+     if ( nbcar >= ARG_LONG_MAX ) 
+     {
+        std::cout << "\nError: Argument too long ( > "
+                  << ARG_LONG_MAX << ")in parameter file."
+                  << std::endl;
+        break;
+     }
+     carlu = fgetc(fd);
+  }
+  *car = '\0';
+  return param;
+}
+
+/*------------------------------------------------------------------------
+ | Role       : Reading of arguments in a parameter file
+ |              (this function is recursive).
+ | Return     : Type   : int
+ |              Role   : length needed to store all the parameters
+ | parameters : filename : char *
+ |              Role     : parameter File name
+ |
+ +------------------------------------------------------------------------*/
+int ArgMgr::ArgLoadFromFile ( const char *filename )
+{
+  int   nbl = 0;
+  char  param[ARG_LONG_MAX+1];
+  FILE  *fch;
+
+  fch = fopen ( filename, ID_RFILE_TEXT );
+  while ( LoadedParam (param, fch ) )
+  {
+    int n = strlen(param);
+    if ( param[0]=='@' )
+    {
+      nbl  += ArgLoadFromFile ( &param[1] );
+    }
+    else
+    {
+      ArgLab [ArgCount] = strcpy ((char *) malloc(n+1), param ) ;
+      nbl += n + 1 ;
+      ArgCount++;
+      if ( ArgCount >= ARGMAXCOUNT ) 
+         break;
+    }
+  }
+  fclose ( fch );
+  return nbl;
+}
+
+/*------------------------------------------------------------------------
+ | Role       : Standard parameters management (on command line)
+ | Return     : Type   : void
+ | parameters : none
+ +------------------------------------------------------------------------*/
+void ArgMgr::ArgStdArgs()
+{
+  char *logfile;
+  FILE *fd;
+
+  if ( (ArgParamOut=ArgMgrValue((char*)ARG_LABEL_PARAMOUT))==0 )
+    ArgParamOut = ARG_DEFAULT_PARAMOUT;
+  if ( (logfile = ArgMgrValue((char*)ARG_LABEL_LOGFILE))!=0) 
+  {
+    if ( *logfile == '\0' )
+       logfile = (char *)ARG_DEFAULT_LOGFILE;
+    fd = fopen ( logfile, "a+" );
+    if ( fd ) 
+    {
+      fprintf ( fd, "%s\n", Appel );
+      fclose  ( fd );
+    }
+  }
+}
+
+/*------------------------------------------------------------------------
+ | Role       : Sets in Upper Case.
+ | Return     : Type   : char *
+ | parameters : char *
+ +------------------------------------------------------------------------*/
+char *ArgMgr::maj ( char *a )
+{
+   char *b = a;
+   while ( *b !=0 ) 
+   {
+      if ( *b<='z' && *b>='a' ) *b = *b+'A'-'a';
+      b++;
+   }
+   return a;
+}
+//-----------------------------------------------------------------------------
+// Print
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmArgMgr.h b/Utilities/ITK/Utilities/gdcm/src/gdcmArgMgr.h
new file mode 100644
index 0000000000000000000000000000000000000000..619dac5a48d3638eb9e66ea1011f8d35040f46cf
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmArgMgr.h
@@ -0,0 +1,112 @@
+/*=========================================================================
+  
+  Program:   gdcm
+  Module:    $RCSfile: gdcmArgMgr.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.2 $
+  
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+  
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+  
+=========================================================================*/
+
+#ifndef  ___ARG_MGR__
+#define  ___ARG_MGR__
+
+#include "gdcmCommon.h"
+#include <stdio.h>  // for FILE
+#include <stdlib.h> // For atof
+
+namespace gdcm
+{
+
+#define ID_RFILE_TEXT        "rt"
+#define ARGMAXCOUNT          100   // Maximum number of arguments
+#define ARG_LONG_MAX         1000
+
+// default file name
+#define ARG_DEFAULT_PARAMOUT "fileout.par"
+#define ARG_DEFAULT_LOGFILE  "gdcm.log"
+
+#define ARG_LABEL_LOGFILE    "LOG"
+#define ARG_LABEL_PARAMOUT   "paramout"
+
+#define START_USAGE(usage)   const char *usage[] = {
+#define FINISH_USAGE         0};
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief   class designed for command line arguments management
+ *          (to make programmer's live easier) 
+ *          NOT Dicom dependant (could be used for any kind 
+ *                              of 'command line program')        
+ */
+ 
+class GDCM_EXPORT ArgMgr
+{
+public:
+   ArgMgr(int argc, char **argv);
+   ~ArgMgr();
+
+   int    ArgMgrDefined           (const char *param);  // Checks if Param is defined
+   char  *ArgMgrValue             (const char *param);  // Returns Param value 
+   const char  *ArgMgrUnused      (void);               // Returns a never used arg.
+   int    ArgMgrSave              (const char *);       // Save of parameters out
+   int    ArgMgrUsage             (const char **usage); // Display program usage 
+   int    ArgMgrPrintUnusedLabels (void);               // Prints unused labels
+
+   int    ArgMgrGetInt   (const char *param, int);  // Gets an int   (with default value)
+   float  ArgMgrGetFloat (const char *param, float);// Gets a float  (with default value)
+   const char  *ArgMgrGetString(const char *param, const char* ext = 0);// Gets a string (with default value)
+   int    ArgMgrGetLabel (const char *param, const char *, int);
+  
+   int    ArgMgrWantInt   (const char *param, const char **usage);  // Demands an int 
+   float  ArgMgrWantFloat (const char *param, const char **usage);  // Demands a float
+   char  *ArgMgrWantString(const char *param, const char **usage);  // Demands a string
+   int    ArgMgrWantLabel (const char *param, char *, const char **usage);
+
+   int   *ArgMgrGetListOfInt   (const char *param, int *);   // Gets a list of int 
+   float *ArgMgrGetListOfFloat (const char *param, int *);   // Gets a list of float
+   char **ArgMgrGetListOfString(const char *param, int *);   // Gets a list of string
+
+   int        *ArgMgrGetIntEnum     (const char *param, int *); // Gets a list of int pairs
+   uint16_t   *ArgMgrGetXInt16Enum  (const char *param, int *); // Gets a list of int16 pairs
+   float      *ArgMgrGetFloatEnum   (const char *param, int *); // Gets a list of float pairs
+
+private :
+
+   int    FiltreLong       (const char *);
+   const char  *LoadedParam(const char *, FILE *);
+   int    ArgLoadFromFile  (const char *);
+   void   ArgStdArgs       (void);
+
+   // These ones are 'general purpose methods'
+   char  *maj       (char *);
+   char  *Majuscule (const char *);
+
+   int       IdStrCountChar  (char *chaine,int caract);
+   int      *IdStrIntEnum    (char *value, int *number);
+   uint16_t *IdStrXInt16Enum (char *value, int *number);
+   float    *IdStrFloatEnum  (char *value, int *number);
+
+// --------------- Attributes ------------------------------
+
+private :
+
+   const char *ArgParamOut;    // Output File Name for param
+
+   char *ArgUsed;              // Used Arguments 
+   char *ArgLab[ARGMAXCOUNT];  // Arguments Labels
+   char *ArgStr[ARGMAXCOUNT];  // Arguments 'strings'
+   int   ArgCount;             // Number of arguments passed 
+   char *Appel;                
+};
+} // end namespace gdcm
+
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmBase.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmBase.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..fd1059a2795572966d0defcfd1c18852a7dd67c5
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmBase.cxx
@@ -0,0 +1,64 @@
+  /*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmBase.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmBase.h"
+
+namespace gdcm 
+{
+//-------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief canonical constructor
+ */
+Base::Base( )
+{
+   PrintLevel = 0;
+}
+
+/**
+ * \brief canonical destructor
+ * \note  If the Header was created by the File constructor,
+ *        it is destroyed by the File
+ */
+Base::~Base()
+{ 
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Print all the object
+ * @param   os The output stream to be written to.
+ * @param indent Indentation string to be prepended during printing
+ */
+void Base::Print(std::ostream &, std::string const & )
+{
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmBase.h b/Utilities/ITK/Utilities/gdcm/src/gdcmBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..eb023307f6cb013515df739ee1154661864cd9d4
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmBase.h
@@ -0,0 +1,59 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmBase.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMBASE_H
+#define GDCMBASE_H
+
+#include "gdcmCommon.h"
+#include <iostream>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/**
+ * \brief Base class of all gdcm classes.
+ * Contains the Print related methods :
+ *  - Print 
+ *  - SetPrintLevel / GetPrintLevel 
+ */
+class GDCM_EXPORT Base
+{
+public:
+   Base( );
+   virtual ~Base();
+
+   /// \brief Printer
+   virtual void Print(std::ostream &os = std::cout,
+                      std::string const & indent = "" );
+
+   /// \brief Sets the print level for the Dicom Header Elements
+   /// \note 0 for Light Print; 1 for 'medium' Print, 2 for Heavy Print
+   void SetPrintLevel(int level) { PrintLevel = level; }
+
+   /// \brief Gets the print level for the Dicom Entries
+   int GetPrintLevel() { return PrintLevel; }
+
+protected:
+   /// \brief Amount of printed details for each Dicom Entries :
+   /// 0 : stands for the least detail level.
+   int PrintLevel;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmBinEntry.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmBinEntry.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..85ec8ce57d6605098c858b45ab11dd321168de84
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmBinEntry.cxx
@@ -0,0 +1,249 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmBinEntry.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.10 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmBinEntry.h"
+#include "gdcmContentEntry.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"  //hidden way to include sstream
+
+#include <fstream>
+#include <iostream> // for std::ios_base, since <ios> does not exist on gcc/Solaris
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor from a given BinEntry
+ */
+BinEntry::BinEntry(DictEntry *e) 
+         :ContentEntry(e)
+{
+   BinArea = 0;
+   SelfArea = true;
+}
+
+/**
+ * \brief   Constructor from a given BinEntry
+ * @param   e Pointer to existing Doc entry
+ */
+BinEntry::BinEntry(DocEntry *e) 
+        : ContentEntry(e->GetDictEntry())
+{
+   Copy(e);
+
+   BinArea = 0;
+   SelfArea = true;
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+BinEntry::~BinEntry()
+{
+   if (BinArea && SelfArea)
+   {
+      delete[] BinArea;
+      BinArea = 0; // let's be carefull !
+   }
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   canonical Writer
+ * @param fp already open file pointer
+ * @param filetype type of the file (ACR, ImplicitVR, ExplicitVR, ...)
+*/
+void BinEntry::WriteContent(std::ofstream *fp, FileType filetype)
+{ 
+   DocEntry::WriteContent(fp, filetype);
+   uint8_t *binArea8 = BinArea; //safe notation
+   size_t lgr = GetLength();
+   if (BinArea) // the binArea was *actually* loaded
+   {
+
+   //  The same operation should be done if we wanted 
+   //  to write image with Big Endian Transfer Syntax, 
+   //  while working on Little Endian Processor
+   // --> forget Big Endian Transfer Syntax writting!
+   //     Next DICOM version will give it up ...
+
+   // -->
+   // --> FIXME 
+   // -->
+   // The stuff looks nice, but it's probably bugged,
+   // since troubles occur on big endian processors (SunSparc, Motorola)
+   // while reading the pixels of a 
+   // gdcm-written Little-Endian 16 bits per pixel image
+
+#if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)
+
+      /// \todo FIXME : Right now, we only care of Pixels element
+      ///       we should deal with *all* the BinEntries
+      ///       Well, not really since we are not interpreting values read...
+
+      // 8 Bits Pixels *are* OB, 16 Bits Pixels *are* OW
+      // -value forced while Reading process-
+      
+      //-->
+      // -->
+      // -->  WARNING
+      // -->        the following lines *looked* very clever, 
+      // -->        but they don't work on big endian processors.
+      // -->        since I've no access for the moment to a big endian proc :-(
+      // -->        I comment them out, to see the result on the dash board 
+      // -->     
+      
+      // --> Revert to initial code : TestWriteSimple hangs on Darwin :-(     
+      if (GetGroup() == 0x7fe0 && GetVR() == "OW")
+      {  
+         uint16_t *binArea16 = (uint16_t*)binArea8;
+         binary_write (*fp, binArea16, lgr );
+      }
+      else
+      { 
+         // For any other VR, BinEntry is re-written as-is
+         binary_write (*fp, binArea8, lgr );
+      }
+            
+      //-->
+      // -->
+      // -->  WARNING      
+      // -->         remove the following line, an uncomment the previous ones, 
+      // -->         if it doesn't work better
+      // -->     
+      /*binary_write ( *fp, binArea8, lgr ); // Elem value*/
+      
+#else
+      binary_write ( *fp, binArea8, lgr ); // Elem value
+#endif //GDCM_WORDS_BIGENDIAN
+
+   }
+   else
+   {
+      // nothing was loaded, but we need to skip space on disc
+      
+      //  --> WARNING : nothing is written; 
+      //  --> the initial data (on the the source image) is lost
+      //  --> user is *not* informed !
+      
+      fp->seekp(lgr, std::ios::cur);
+   }
+}
+
+/**
+ * \brief Sets the value (non string) of the current Dicom Header Entry
+ */
+void BinEntry::SetBinArea( uint8_t *area, bool self )  
+{ 
+   if (BinArea && SelfArea)
+      delete[] BinArea;
+
+   BinArea = area;
+   SelfArea=self;
+}
+
+/**
+ * \brief   Compute the full length of the elementary DataEntry (not only value
+ *          length) depending on the VR.
+ */
+uint32_t BinEntry::ComputeFullLength()
+{
+   return GetFullLength();
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+   
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Prints a BinEntry (Dicom entry)
+ * @param   os ostream we want to print in
+ * @param indent Indentation string to be prepended during printing
+ */
+void BinEntry::Print(std::ostream &os, std::string const & )
+{
+   os << "B ";
+   DocEntry::Print(os);
+   itksys_ios::ostringstream s;
+   void* binArea = GetBinArea();
+   if (binArea)
+   {
+      if ( GetVR() == "FL" )
+      {
+         int l = GetReadLength()/4 - 1;
+         float *beg = (float *)GetBinArea();
+         s << " [" << *beg;
+         if ( l!= 0)
+            for (int i=0;i<l;i++)
+            {
+               beg++;
+               s << "\\" << *beg;
+            }
+            s << "]";
+      }
+      else if ( GetVR() == "FD" )
+      {
+         int l = GetReadLength()/8 - 1;
+         double *beg = (double *)GetBinArea();
+         s << " [" << *beg;
+         if ( l!= 0)
+            for (int i=0;i<l;i++)
+            {
+               beg++;
+               s << "\\" << *beg;
+            }
+            s << "]";
+      }
+      else
+      { 
+         if ( Util::IsCleanArea( GetBinArea(),GetLength()  ) )
+         {
+            std::string cleanString = 
+                   Util::CreateCleanString( GetBinArea(),GetLength()  );
+            s << " [" << cleanString << "]";
+         }
+         else
+         {
+            //s << " [" << GetValue()
+            s << " [" << GDCM_BINLOADED << ";"
+              << "length = " << GetLength() << "]";
+         } 
+      }
+   }
+   else
+   {
+      if ( GetLength() == 0 )
+      {
+         s << " []";
+      }
+      else 
+      {
+         s << " [" <<GetValue() << "]";
+      }         
+   }
+   os << s.str();
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmBinEntry.h b/Utilities/ITK/Utilities/gdcm/src/gdcmBinEntry.h
new file mode 100644
index 0000000000000000000000000000000000000000..8fb4cb0ebd435f1853f0703fa21e3a3019da315d
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmBinEntry.h
@@ -0,0 +1,73 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmBinEntry.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMBINENTRY_H
+#define GDCMBINENTRY_H
+
+#include "gdcmContentEntry.h"
+#include <iostream>
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief   Any Dicom Document (File or DicomDir) contains 
+ *           a set of DocEntry - Dicom entries - 
+ *          BinEntry is an elementary DocEntry (i.e. a ContentEntry, 
+ *           as opposed to SeqEntry) whose content is non std::string
+ *          representable
+ *          BinEntry is a specialisation of ContentEntry
+ */
+ 
+class GDCM_EXPORT BinEntry  : public ContentEntry
+{
+public:
+   BinEntry( DictEntry *e );
+   BinEntry( DocEntry *d ); 
+
+   ~BinEntry();
+   
+   void Print( std::ostream &os = std::cout, std::string const &indent = "" );
+
+   void WriteContent( std::ofstream *fp, FileType ft);
+
+   /// \brief Returns the area value of the current Dicom Entry
+   ///  when it's not string-translatable (e.g : LUT table, overlay, icon)         
+   uint8_t *GetBinArea()  { return BinArea; }
+   void  SetBinArea( uint8_t *area, bool self = true );
+
+   uint32_t ComputeFullLength();
+
+   /// \brief Sets SelfArea
+   void SetSelfArea(bool area) { SelfArea = area; }
+   /// \brief Returns SelfArea
+   bool IsSelfArea() { return SelfArea; }
+
+private:
+   /// \brief memory area to hold 'non std::string' representable values 
+   ///       (ie : Lookup Tables, overlays, icons)   
+   uint8_t *BinArea;
+   /// \brief Whether BinEntry has its own BinArea or not
+   bool SelfArea;
+};
+
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmCommon.h b/Utilities/ITK/Utilities/gdcm/src/gdcmCommon.h
new file mode 100644
index 0000000000000000000000000000000000000000..587fe3cdaa8b38762710c0f308e89d854c54dfab
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmCommon.h
@@ -0,0 +1,233 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmCommon.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.23 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMCOMMON_H
+#define GDCMCOMMON_H
+
+#include "gdcmConfigure.h"
+
+//-----------------------------------------------------------------------------
+//This is needed when compiling in debug mode
+#ifdef _MSC_VER
+// 'identifier' : class 'type' needs to have dll-interface to be used by
+// clients of class 'type2'
+#pragma warning ( disable : 4251 )
+// non dll-interface class 'type' used as base for dll-interface class 'type2'
+#pragma warning ( disable : 4275 )
+// 'identifier' : identifier was truncated to 'number' characters in the
+// debug information
+#pragma warning ( disable : 4786 )
+//'identifier' : decorated name length exceeded, name was truncated
+#pragma warning ( disable : 4503 )
+// C++ exception specification ignored except to indicate a 
+// function is not __declspec(nothrow)
+#pragma warning ( disable : 4290 )
+// signed/unsigned mismatch
+#pragma warning ( disable : 4018 )
+// return type for 'identifier' is '' (ie; not a UDT or reference to UDT. Will
+// produce errors if applied using infix notation
+#pragma warning ( disable : 4284 )
+// 'type' : forcing value to bool 'true' or 'false' (performance warning)
+// //#pragma warning ( disable : 4800 )
+#endif //_MSC_VER
+
+//-----------------------------------------------------------------------------
+#ifdef CMAKE_HAVE_STDINT_H
+   #include <stdint.h>
+#else
+#ifdef CMAKE_HAVE_INTTYPES_H
+   // Old system only have this
+   #include <inttypes.h>   // For uint8_t uint16_t and uint32_t
+#else
+// Broken plateforms do not respect C99 and do not provide those typedef
+// Special case for recent Borland compiler, comes with stdint.h
+#if defined(_MSC_VER) || defined(__BORLANDC__) && (__BORLANDC__ < 0x0560)  \
+                      || defined(__MINGW32__)
+typedef  signed char         int8_t;
+typedef  signed short        int16_t;
+typedef  signed int          int32_t;
+typedef  unsigned char       uint8_t;
+typedef  unsigned short      uint16_t;
+typedef  unsigned int        uint32_t;
+#else
+#error "Sorry your plateform is not supported"
+#endif // defined(_MSC_VER) || defined(__BORLANDC__) && (__BORLANDC__ < 0x0560)  || defined(__MINGW32__)
+#endif // CMAKE_HAVE_INTTYPES_H
+#endif // CMAKE_HAVE_STDINT_H
+
+// Basically for VS6 and bcc 5.5.1:
+#ifndef UINT32_MAX
+#define UINT32_MAX    (4294967295U)
+#endif
+
+#if defined(_WIN32) && defined(BUILD_SHARED_LIBS)
+  #ifdef gdcm_EXPORTS
+    #define GDCM_EXPORT __declspec( dllexport )
+  #else
+    #define GDCM_EXPORT __declspec( dllimport )
+  #endif
+#else
+  #define GDCM_EXPORT
+#endif
+
+#include <string>
+#define FASTTAGKEY 0
+
+// FIXME: Should rewrite this:
+#if FASTTAGKEY
+#include <iostream>
+#include <iomanip>
+#endif
+#if defined(_MSC_VER) && (_MSC_VER == 1200)
+/* ostream operator for std::string since VS6 does not provide it*/
+#include <iostream>
+#endif
+
+
+//-----------------------------------------------------------------------------
+/// \brief namespace for Grass root DiCoM
+namespace gdcm
+{
+
+// Centralize information about the gdcm dictionary in only one file:
+#ifndef PUB_DICT_PATH
+#  define PUB_DICT_PATH   "../Dicts/"
+#endif
+#define PUB_DICT_NAME     "DicomV3Dict"
+#define PUB_DICT_FILENAME "gdcm.dic"
+#define DICT_ELEM         "DicomDir.dic"
+#define DICT_TS           "dicomTS.dic"
+#define DICT_VR           "dicomVR.dic"
+#define DICT_GROUP_NAME   "DictGroupName.dic"
+
+GDCM_EXPORT extern const std::string GDCM_UNKNOWN;
+GDCM_EXPORT extern const std::string GDCM_UNFOUND;
+GDCM_EXPORT extern const std::string GDCM_BINLOADED;
+GDCM_EXPORT extern const std::string GDCM_NOTLOADED;
+GDCM_EXPORT extern const std::string GDCM_UNREAD;
+GDCM_EXPORT extern const std::string GDCM_NOTASCII;
+GDCM_EXPORT extern const std::string GDCM_PIXELDATA;
+/// \brief TagKey is made to hold the standard Dicom Tag 
+///               (Group number, Element number)
+/// Instead of using the two '16 bits integers' as the Hask Table key, we
+/// converted into a string (e.g. 0x0018,0x0050 converted into "0018|0050")
+/// It appears to be a huge waste of time.
+/// We'll fix the mess up -without any change in the API- as soon as the bench
+/// marks are fully performed.
+
+#if FASTTAGKEY
+typedef union   {
+      uint16_t  tab[2];
+      uint32_t  tagkey;
+    } TagKey;
+/* ostream operator for TagKey */
+inline std::ostream& operator<<(std::ostream& _O, TagKey _val)
+{
+  _O.setf( std::ios::right);
+  return (_O << std::hex << std::setw( 4 ) << std::setfill( '0' )
+     << _val.tab[0] << '|' << std::setw( 4 ) << std::setfill( '0' )
+     << _val.tab[1] << std::setfill( ' ' ) << std::dec);
+}
+inline bool operator==(TagKey _self, TagKey _val)
+{
+  return _self.tagkey == _val.tagkey;
+}
+inline bool operator<(TagKey _self, TagKey _val)
+{
+  // This expression is a tad faster but PrintFile output
+  // is more difficult to read
+  //return _self.tagkey < _val.tagkey;
+
+  // More usal order of dicom tags:
+  if( _self.tab[0] == _val.tab[0] )
+    return _self.tab[1] < _val.tab[1];
+  return _self.tab[0] < _val.tab[0];
+}
+#else
+typedef std::string TagKey;
+#endif
+#if defined(_MSC_VER) && (_MSC_VER == 1200)
+// Doing everything within gdcm namespace to avoid polluting 3d party software
+inline std::ostream& operator<<(std::ostream& _O, std::string _val)
+{
+  return _O << _val.c_str();
+}
+#endif
+
+/// \brief TagName is made to hold the 'non hexa" fields (VR, VM, Name) 
+///        of Dicom Entries
+typedef std::string TagName;
+
+/// \brief various types of a DICOM file (for internal use only)
+enum FileType {
+   Unknown = 0,
+   ExplicitVR, // DicomDir is in this case. Except when it's ImplicitVR !...
+   ImplicitVR,
+   ACR,
+   ACR_LIBIDO,
+   JPEG
+};
+
+/// \brief type of the elements composing a DICOMDIR (for internal use only)
+enum DicomDirType {
+   DD_UNKNOWN = 0,
+   DD_META,
+   DD_PATIENT,
+   DD_STUDY,
+   DD_SERIE,
+   DD_IMAGE,
+   DD_VISIT
+};
+
+/// \brief comparison operators (as used in SerieHelper::AddRestriction() )
+enum CompOperators {
+   GDCM_EQUAL = 0,
+   GDCM_DIFFERENT,
+   GDCM_GREATER,
+   GDCM_GREATEROREQUAL,
+   GDCM_LESS,
+   GDCM_LESSOREQUAL
+};
+
+/// \brief Loading mode
+enum LodModeType
+{
+   LD_ALL         = 0x00000000, // Load all
+   LD_NOSEQ       = 0x00000001, // Don't load Sequences
+   LD_NOSHADOW    = 0x00000002, // Don't load odd groups
+   LD_NOSHADOWSEQ = 0x00000004  // Don't load Sequences if they belong 
+                                //            to an odd group
+                                // (*exclusive* from LD_NOSEQ and LD_NOSHADOW)
+};
+
+/**
+ * \brief structure, for internal use only
+ */  
+struct Element
+{
+   /// Dicom Group number
+   unsigned short int Group;
+   /// Dicom Element number
+   unsigned short int Elem;
+   /// value (coded as a std::string) of the Element
+   std::string Value;
+};
+
+} //namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmContentEntry.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmContentEntry.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e9bbe1ff36c91a00aac6bb7a5d14f11facb89a60
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmContentEntry.cxx
@@ -0,0 +1,82 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmContentEntry.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmContentEntry.h"
+#include "gdcmVR.h"
+#include "gdcmTS.h"
+#include "gdcmGlobal.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+
+#include <fstream>
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor for a given DictEntry
+ * @param   e Pointer to existing dictionary entry
+ */
+ContentEntry::ContentEntry(DictEntry *e) 
+            : DocEntry(e)
+{
+   Value = GDCM_UNFOUND;
+}
+
+/**
+ * \brief   Constructor for a given DocEntry
+ * @param   e Pointer to existing Doc entry
+ */
+ContentEntry::ContentEntry(DocEntry *e)
+            : DocEntry(e->GetDictEntry())
+{
+   Copy(e);
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+ContentEntry::~ContentEntry ()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Print
+
+//-----------------------------------------------------------------------------
+// Public
+void ContentEntry::Copy(DocEntry *doc)
+{
+   DocEntry::Copy(doc);
+
+   ContentEntry *entry = dynamic_cast<ContentEntry *>(doc);
+   if ( entry )
+      Value = entry->Value;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmContentEntry.h b/Utilities/ITK/Utilities/gdcm/src/gdcmContentEntry.h
new file mode 100644
index 0000000000000000000000000000000000000000..ddf07b236d3613ce5cefa3b7743ce436e124bc64
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmContentEntry.h
@@ -0,0 +1,70 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmContentEntry.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMCONTENTENTRY_H
+#define GDCMCONTENTENTRY_H
+
+#include "gdcmDocEntry.h"
+
+#include <iostream>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/**
+ * \brief   Any Dicom Document (File or DicomDir) contains 
+ *           a set of DocEntry  - Dicom entries -
+ *           (when successfuly parsed against a given Dicom dictionary)
+ *          ContentEntry is an elementary DocEntry (as opposed to SeqEntry).
+ *          Depending on the type of its content,
+ *          ContentEntry is specialized as a ValEntry or a BinEntry
+ */
+class GDCM_EXPORT ContentEntry  : public DocEntry
+{
+public:
+   virtual void WriteContent(std::ofstream *fp, FileType filetype) = 0;
+
+   /// Sets the value (string) of the current Dicom entry
+   virtual void SetValue(std::string const &val) { Value = val; }
+   /// \brief Returns the 'Value' (e.g. "Dupond^Marcel") converted 
+   /// into a 'string', event if it's physically stored on disk as an integer
+   /// (e.g. : 0x000c returned as "12")
+   std::string const &GetValue() const { return Value; }
+
+   void Copy(DocEntry *doc);
+
+protected:
+   // Contructors are protected, not to be invoked by end user.
+   ContentEntry(DictEntry *e);
+   ContentEntry(DocEntry *d); 
+   // Destructor is protected, not to be invoked by end user.
+   ~ContentEntry();
+
+private:
+// Members :
+   /// \brief Dicom entry value, internaly represented as a std::string.
+   ///        The Value Representation (\ref VR) is independently used
+   ///        in order to interpret (decode) this field.
+   std::string Value;
+};
+
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDebug.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDebug.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..40469262501db614cff098817606edefd19771f0
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDebug.cxx
@@ -0,0 +1,115 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDebug.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.5 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDebug.h"
+#include <iostream>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Warning message level to be displayed
+static bool DebugFlag   = false;
+static bool DebugToFile = false;
+static std::ofstream DebugFile;
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+Debug::Debug()
+{
+}
+
+Debug::~Debug()
+{
+  if ( DebugFile.is_open() )
+      DebugFile.close();     
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Sets the debug flag
+ * @param   flag Set the debug flag
+ */ 
+void Debug::SetDebugFlag (bool flag) 
+{
+   DebugFlag = flag;
+}
+
+/**
+ * \brief   Gets the debug flag value
+ * @return debug flag value
+ */ 
+bool Debug::GetDebugFlag ()
+{
+   return DebugFlag;
+}
+
+/**
+ * \brief   Accessor
+ * @param   flag whether we want to redirect to file
+ */ 
+void Debug::SetDebugToFile (bool flag) 
+{
+   DebugToFile = flag;
+}
+
+/**
+ * \brief   Accessor to know whether debug info are redirected to file
+ */ 
+bool Debug::GetDebugToFile ()
+{
+   return DebugToFile;
+}
+
+/**
+ * \brief Set the filename the debug stream should be redirect to
+ *        Settting a filename also sets DebugToFile to true
+ * @param   filename  File to redirect debug info
+ *          Absolutely nothing is check. You have to pass in
+ *          a correct filename
+ */ 
+void Debug::SetDebugFilename (std::string const &filename)
+{
+   DebugToFile = true;  // Just in case ... 
+   DebugFlag   = true;  // Just in case ...
+   if ( DebugFile.is_open() )
+      DebugFile.close();
+   DebugFile.open( filename.c_str() );
+}
+
+/**
+ * \brief Internal use only. Allow us to retrieve the static from anywhere
+ *        in gdcm code
+ * @return Debug file
+ */
+std::ofstream &Debug::GetDebugFile ()
+{
+  return DebugFile;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+   
+//-----------------------------------------------------------------------------
+// Print
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDebug.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDebug.h
new file mode 100644
index 0000000000000000000000000000000000000000..db5c38da90b1413e4c8583b9cb02951f7df2f000
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDebug.h
@@ -0,0 +1,251 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDebug.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.8 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDEBUG_H
+#define GDCMDEBUG_H
+
+#include "gdcmCommon.h"
+
+#include <itksys/ios/sstream>
+#include <fstream>
+#include <assert.h>
+#include <errno.h>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+
+/**
+ * \brief Debug is an object for debugging in program.
+ * It has 2 debugging modes :
+ *  - error : for bad library use, seriously wrong DICOM
+ *  - debug : for information/debug messages
+ *  - warning : for warning about DICOM quality (kosher)
+ *  - assert : design by contract implementation. A function should have 
+ *             proper input and proper output. 
+ *             (should not happen, not user controlled)
+ * 
+ * A debugging message is only shown if the flag is on (DebugFlag)
+ * This is static var and can be set at beginning of code:
+ *         gdcm::Debug::SetDebugOn();
+ */
+class GDCM_EXPORT Debug
+{
+public:
+   Debug();
+   ~Debug();
+
+   /// \brief This is a global flag that controls whether any debug, warning
+   ///        messages are displayed.
+   static void SetDebugFlag (bool flag);
+   static bool GetDebugFlag ();
+   /// \brief Sets the Debug Flag to true
+   static void DebugOn  () { SetDebugFlag(true);  }
+   /// \brief Sets the Debug Flag to false
+   static void DebugOff () { SetDebugFlag(false); }
+
+   /// \brief This is a global flag that controls if debug are redirected
+   ///        to a file or not
+   static void SetDebugToFile (bool flag);
+   static bool GetDebugToFile ();
+   /// \brief Next debug messages will be sent in the debug file
+   static void DebugToFileOn  () { SetDebugToFile(true);  }
+   /// \brief Next debug messages will be sent in the standard output
+   static void DebugToFileOff () { SetDebugToFile(false); }
+
+   static void SetDebugFilename (std::string const &filename);
+
+   static std::ofstream &GetDebugFile ();
+};
+
+} // end namespace gdcm
+
+// Here we define function this is the only way to be able to pass
+// stuff with indirection like:
+// gdcmDebug( "my message:" << i << '\t' ); 
+// You cannot use function unless you use vnsprintf ...
+
+// __FUNCTION is not always defined by preprocessor
+// In c++ we should use __PRETTY_FUNCTION__ instead...
+#ifdef GDCM_COMPILER_HAS_FUNCTION
+// Handle particular case for GNU C++ which also defines __PRETTY_FUNCTION__
+// which is a lot nice in C++
+#ifdef __BORLANDC__
+#  define __FUNCTION__ __FUNC__
+#endif
+#ifdef __GNUC__
+#  define GDCM_FUNCTION __PRETTY_FUNCTION__
+#else
+#  define GDCM_FUNCTION __FUNCTION__ 
+#endif //__GNUC__
+#else
+#  define GDCM_FUNCTION "<unknow>"
+#endif //GDCM_COMPILER_HAS_FUNCTION
+
+/**
+ * \brief   Debug
+ * @param msg message part
+ */
+#ifdef NDEBUG
+#define gdcmDebugMacro(msg) {}
+#else
+#define gdcmDebugMacro(msg)                                 \
+{                                                           \
+   if( Debug::GetDebugFlag() )                              \
+   {                                                        \
+   itksys_ios::ostringstream osmacro;                              \
+   osmacro << "Debug: In " __FILE__ ", line " << __LINE__   \
+           << ", function " << GDCM_FUNCTION << '\n'        \
+           << "Last system error was: " << strerror(errno)  \
+           << '\n' << msg << "\n\n";                        \
+   if( Debug::GetDebugToFile() )                            \
+      Debug::GetDebugFile() << osmacro.str() << std::endl;  \
+   else                                                     \
+      std::cerr << osmacro.str() << std::endl;              \
+   }                                                        \
+}
+#endif //NDEBUG
+
+/**
+ * \brief   Warning
+ * @param msg message part
+ */
+#ifdef NDEBUG
+#define gdcmWarningMacro(msg) {}
+#else
+#define gdcmWarningMacro(msg)                               \
+{                                                           \
+   if( Debug::GetDebugFlag() )                              \
+   {                                                        \
+   itksys_ios::ostringstream osmacro;                              \
+   osmacro << "Warning: In " __FILE__ ", line " << __LINE__ \
+           << ", function " << GDCM_FUNCTION << "\n"        \
+           << msg << "\n\n";                                \
+   if( Debug::GetDebugToFile() )                            \
+      Debug::GetDebugFile() << osmacro.str() << std::endl;  \
+   else                                                     \
+      std::cerr << osmacro.str() << std::endl;              \
+   }                                                        \
+}
+#endif //NDEBUG
+
+/**
+ * \brief   Error 
+ * @param msg second message part 
+ */
+#ifdef NDEBUG
+#define gdcmErrorMacro(msg) {}
+#else
+#define gdcmErrorMacro(msg)                                 \
+{                                                           \
+   itksys_ios::ostringstream osmacro;                              \
+   osmacro << "Error: In " __FILE__ ", line " << __LINE__   \
+           << ", function " << GDCM_FUNCTION << '\n'        \
+           << msg << "\n\n";                                \
+   if( Debug::GetDebugToFile() )                            \
+      Debug::GetDebugFile() << osmacro.str() << std::endl;  \
+   else                                                     \
+      std::cerr << osmacro.str() << std::endl;              \
+}
+#endif //NDEBUG
+
+/**
+ * \brief   Assert 
+ * @param arg argument to test
+ *        An easy solution to pass also a message is to do:
+ *        gdcmAssertMacro( "my message" && 2 < 3 )
+ */
+#ifdef NDEBUG
+#define gdcmAssertMacro(arg) {}
+#else
+#define gdcmAssertMacro(arg)                                \
+{                                                           \
+   if( !(arg) )                                             \
+   {                                                        \
+   itksys_ios::ostringstream osmacro;                              \
+   osmacro << "Assert: In " __FILE__ ", line " << __LINE__  \
+           << ", function " << GDCM_FUNCTION                \
+           << "\n\n";                                       \
+   if( Debug::GetDebugToFile() )                            \
+      Debug::GetDebugFile() << osmacro.str() << std::endl;  \
+   else                                                     \
+      std::cerr << osmacro.str() << std::endl;              \
+   assert ( arg );                                          \
+   }                                                        \
+}
+#endif //NDEBUG
+
+//-----------------------------------------------------------------------------
+//
+// Define GDCM_LEGACY macro to mark legacy methods where they are
+// declared in their class.
+// 
+// WARNING : Don't try to use it with 'inline' methods ! 
+//
+//Example usage:
+//
+//   // @deprecated Replaced by MyOtherMethod() as of gdcm 2.0.
+//   GDCM_LEGACY(void MyMethod());
+#if defined(GDCM_LEGACY_REMOVE)
+  // Remove legacy methods completely.
+# define GDCM_LEGACY(method)
+#elif defined(GDCM_LEGACY_SILENT) || defined(SWIG)
+  // Provide legacy methods with no warnings.
+# define GDCM_LEGACY(method) method
+#else
+  // Setup compile-time warnings for uses of deprecated methods if
+  // possible on this compiler.
+# if defined(__GNUC__) && !defined(__INTEL_COMPILER) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#if defined(__APPLE__) && (__GNUC__ == 3) && (__GNUC_MINOR__ == 3)
+// Seems like there is a bug in APPLE gcc for deprecated attribute and ctor
+// This is fixed in g++ 4.0 (Tiger)
+#  define GDCM_LEGACY(method) method
+#else
+#  define GDCM_LEGACY(method) method __attribute__((deprecated))
+#endif
+# elif defined(_MSC_VER) && _MSC_VER >= 1300
+#  define GDCM_LEGACY(method) __declspec(deprecated) method
+# else
+#  define GDCM_LEGACY(method) method
+# endif
+#endif
+
+// Macros to create runtime deprecation warning messages in function
+// bodies.  Example usage:
+//
+//   void MyClass::MyOldMethod()
+//   {
+//     GDCM_LEGACY_BODY(MyClass::MyOldMethod, 2.0);
+//   }
+//
+//   void MyClass::MyMethod()
+//   {
+//     GDCM_LEGACY_REPLACED_BODY(MyClass::MyMethod, 5.0,
+//                               MyClass::MyOtherMethod);
+//   }
+#if defined(GDCM_LEGACY_REMOVE) || defined(GDCM_LEGACY_SILENT)
+# define GDCM_LEGACY_BODY(method, version)
+# define GDCM_LEGACY_REPLACED_BODY(method, version, replace)
+#else
+# define GDCM_LEGACY_BODY(method, version) \
+  gdcmWarningMacro(#method " was deprecated for gdcm" #version " and will be removed in a future version.")
+# define GDCM_LEGACY_REPLACED_BODY(method, version, replace) \
+  gdcmWarningMacro(#method " was deprecated for gdcm" #version " and will be removed in a future version.  Use " #replace " instead.")
+#endif
+
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDefaultDicts.cxx.in b/Utilities/ITK/Utilities/gdcm/src/gdcmDefaultDicts.cxx.in
new file mode 100644
index 0000000000000000000000000000000000000000..417dfcb8033788450cfcf9af6bbab4dbb1231846
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDefaultDicts.cxx.in
@@ -0,0 +1,119 @@
+/*=========================================================================
+
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDefaultDicts.cxx.in,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.6 $
+
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#ifndef GDCMDEFAULTDICTS_H
+#define GDCMDEFAULTDICTS_H
+
+#include "gdcmDict.h"
+#include "gdcmDictEntry.h"
+#include "gdcmTS.h"
+#include "gdcmVR.h"
+#include "gdcmDictGroupName.h"
+#include "gdcmDicomDirElement.h"
+
+namespace gdcm
+{
+
+typedef struct
+{
+   uint16_t group;
+   uint16_t element;
+   const char *vr;
+   const char *vm;
+   const char *name;
+} DICT_ENTRY;
+
+static DICT_ENTRY datadir[] = {
+@DICOM_DATA_DICTIONARY@
+};
+
+void FillDefaultDataDict(Dict *d)
+{
+   unsigned int i = 0;
+   DICT_ENTRY n = datadir[i];
+   while( n.name != 0 )
+   {
+      const DictEntry e( n.group, n.element, n.vr, n.vm, n.name);
+      d->AddEntry( e );
+      n = datadir[++i];
+   }
+}
+
+void FillDefaultTSDict(TSHT &ts)
+{
+@DICOM_TS_DICTIONARY@
+}
+
+void FillDefaultVRDict(VRHT &vr)
+{
+@DICOM_VR_DICTIONARY@
+}
+
+void FillDefaultDictGroupName(DictGroupNameHT &groupName)
+{
+@DICT_GROUP_NAME_DICTIONARY@
+}
+
+typedef struct
+{
+   const char *type;
+   unsigned short group;
+   unsigned short element;
+   const char *value;
+} ELEMENT;
+
+static ELEMENT dataElement[] = {
+@DICOM_DIR_DICTIONARY@
+};
+
+void FillDefaultDIRDict(DicomDirElement *dde)
+{
+   unsigned int i = 0;
+   ELEMENT e = dataElement[i];
+   Element elem;
+   DicomDirType type;
+   std::string strType;
+
+   while( e.type != 0 )
+   {
+      // Force to use the string comparision operator ==
+      strType = e.type;
+      if( strType == "metaElem" )
+         type = DD_META;
+      else if( strType == "patientElem" )
+         type = DD_PATIENT;
+      else if( strType == "studyElem" )
+         type = DD_STUDY;
+      else if( strType == "serieElem" )
+         type = DD_SERIE;
+      else if( strType == "imageElem" )
+         type = DD_IMAGE;
+      else
+         type = DD_UNKNOWN;
+
+      elem.Group = e.group;
+      elem.Elem  = e.element;
+      elem.Value = e.value;
+      dde->AddEntry( type, elem);
+      e = dataElement[++i];
+   }
+}
+
+} //end gdcm namespace
+#endif
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDir.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDir.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f57cc05201d2baed51503af5db077c3ffdb3f344
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDir.cxx
@@ -0,0 +1,1228 @@
+/*=========================================================================
+  
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDir.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.12 $
+  
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+  
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+  
+=========================================================================*/
+
+//-----------------------------------------------------------------------------
+//  For full DICOMDIR description, see:
+//  PS 3.3-2003, pages 731-750
+//-----------------------------------------------------------------------------
+#include "gdcmDicomDir.h"
+#include "gdcmDicomDirObject.h"
+#include "gdcmDicomDirStudy.h"
+#include "gdcmDicomDirSerie.h"
+#include "gdcmDicomDirVisit.h"
+#include "gdcmDicomDirImage.h"
+#include "gdcmDicomDirPatient.h"
+#include "gdcmDicomDirMeta.h"
+#include "gdcmDicomDirElement.h"
+#include "gdcmDirList.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+#include "gdcmGlobal.h"
+#include "gdcmFile.h"
+#include "gdcmSeqEntry.h"
+#include "gdcmSQItem.h"
+#include "gdcmValEntry.h"
+
+#include <fstream>
+#include <string>
+#include <algorithm>
+#include <sys/types.h>
+
+#ifdef _MSC_VER
+#   define getcwd _getcwd
+#endif
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#   include <direct.h>
+#else
+#   include <unistd.h>
+#endif
+
+#if defined(__BORLANDC__)
+   #include <mem.h> // for memset
+#endif
+
+// ----------------------------------------------------------------------------
+//         Note for future developpers
+// ----------------------------------------------------------------------------
+//
+//  Dicom PS 3.3 describes the relationship between Directory Records, as follow
+//    (see also PS 4.3, 2004, page 50 for Entity-Relationship model)
+//
+//  Directory Record Type      Directory Record Types which may be included
+//                                in the next lower-level directory Entity
+//
+// (Root directory Entity)     PATIENT, TOPIC, PRIVATE
+//
+// PATIENT                     STUDY, PRIVATE
+//
+// STUDY                       SERIES, VISIT, RESULTS, STUDY COMPONENT, PRIVATE
+//
+// SERIES                      IMAGE, OVERLAYS, MODALITY LUT, VOI LUT,
+//                             CURVE, STORED PRINT, RT DOSE, RT STRUCTURE SET
+//                             RT PLAN, RT TREAT RECORD, PRESENTATION, WAVEFORM,
+//                             SR DOCUMENT, KEY OBJECT DOC, SPECTROSCOPY,
+//                             RAW DATA, REGISTRATION, FIDUCIAL, PRIVATE,
+//                             ENCAP DOC
+// IMAGE
+// OVERLAY
+// MODALITY LUT
+// VOI LUT
+// CURVE
+// STORED PRINT
+// RT DOSE
+// RT STRUCTURE SET
+// RT PLAN
+// RT TREAT RECORD
+// PRESENTATION
+// WAVEFORM
+// SR DOCUMENT
+// KEY OBJECT DOC
+// SPECTROSCOPY
+// RAW DATA
+// REGISTRATION
+// FIDUCIAL
+// PRIVATE
+// ENCAP DOC
+// 
+// ----------------------
+// The current gdcm version only deals with :
+//
+// (Root directory Entity)     PATIENT
+// PATIENT                     STUDY
+// STUDY                       SERIES
+// STUDY                       VISIT 
+// SERIES                      IMAGE
+// IMAGE                       /
+//
+// DicomDir::CreateDicomDir will have to be completed
+// Treelike structure management will have to be upgraded
+// ----------------------------------------------------------------------------
+    
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor : creates an empty DicomDir
+ */
+DicomDir::DicomDir()
+         :Document( )
+{
+   Initialize();  // sets all private fields to NULL
+   ParseDir = false;
+   NewMeta();
+}
+
+#ifndef GDCM_LEGACY_REMOVE
+/**
+ * \brief Constructor Parses recursively the directory and creates the DicomDir
+ *        or uses an already built DICOMDIR, depending on 'parseDir' value.
+ * @param fileName  name 
+ *                      - of the root directory (parseDir = true)
+ *                      - of the DICOMDIR       (parseDir = false)
+ * @param parseDir boolean
+ *                      - true if user passed an entry point 
+ *                        and wants to explore recursively the directories
+ *                      - false if user passed an already built DICOMDIR file
+ *                        and wants to use it 
+ * @deprecated use : new DicomDir() + [ SetLoadMode(lm) + ] SetDirectoryName(name)
+ *              or : new DicomDir() + SetFileName(name)
+ */
+DicomDir::DicomDir(std::string const &fileName, bool parseDir ):
+   Document( )
+{
+   // At this step, Document constructor is already executed,
+   // whatever user passed (either a root directory or a DICOMDIR)
+   // and whatever the value of parseDir was.
+   // (nothing is cheked in Document constructor, to avoid overhead)
+
+   ParseDir = parseDir;
+   SetLoadMode (LD_ALL); // concerns only dicom files
+   SetFileName( fileName );
+   Load( );
+}
+#endif
+
+/**
+ * \brief  Canonical destructor 
+ */
+DicomDir::~DicomDir() 
+{
+   SetStartMethod(NULL,NULL,NULL);
+   SetProgressMethod(NULL,NULL,NULL);
+   SetEndMethod(NULL,NULL,NULL);
+
+   ClearPatient();
+   if ( MetaElems )
+   {
+      delete MetaElems;
+   }
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+/**
+ * \brief   Loader. use SetFileName(fn) 
+ *                  or SetLoadMode(lm) + SetDirectoryName(dn)  before !  
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
+ */
+bool DicomDir::Load( ) 
+{
+   // We should clean out anything that already exists.
+   Initialize();  // sets all private fields to NULL
+
+   if (!ParseDir)
+   {
+      if ( ! this->Document::Load( ) )
+         return false;
+   }
+   return DoTheLoadingJob( );   
+}
+
+#ifndef GDCM_LEGACY_REMOVE
+/**
+ * \brief   Loader. (DEPRECATED : kept not to break the API)
+ * @param   fileName file to be open for parsing
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
+ * @deprecated use SetFileName(n) + Load() instead
+ */
+bool DicomDir::Load(std::string const &fileName ) 
+{
+   // We should clean out anything that already exists.
+   Initialize();  // sets all private fields to NULL
+
+   SetFileName( fileName );
+   if (!ParseDir)
+   {
+      if ( ! this->Document::Load( ) )
+         return false;
+   }
+   return DoTheLoadingJob( );
+}
+
+/// DEPRECATED : use SetDirectoryName(dname) instead
+/**
+ * \brief   Loader. (DEPRECATED : kept not to break the API)
+ * @param   paseDir Parse Dir
+ * @deprecated use SetDirectoryName(dname) instead
+ */
+void DicomDir::SetParseDir(bool parseDir)
+{
+   ParseDir = parseDir;
+}
+#endif
+
+/**
+ * \brief   Does the Loading Job (internal use only)
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
+ */
+bool DicomDir::DoTheLoadingJob( ) 
+{
+   // We should clean out anything that already exists.
+   Initialize();  // sets all private fields to NULL
+
+   if (!ParseDir)
+   {
+   // Only if user passed a DICOMDIR
+   // ------------------------------
+      Fp = 0;
+      if ( !OpenFile() )
+      {
+         return false;
+      }
+      if (!Document::Load() )
+      {
+         return false;
+      }
+
+      if ( GetFirstEntry() == 0 ) // when user passed a Directory to parse
+      {
+         gdcmWarningMacro( "Entry HT empty for file: "<< GetFileName());
+         return false;
+      }
+      // Directory record sequence
+      DocEntry *e = GetDocEntry(0x0004, 0x1220);
+      if ( !e )
+      {
+         gdcmWarningMacro( "NO 'Directory record sequence' (0x0004,0x1220)"
+                          << " in file " << GetFileName());
+         return false;
+      }
+      else
+         CreateDicomDir();
+   }
+   else
+   {
+   // Only if user passed a root directory
+   // ------------------------------------
+      if ( GetFileName() == "." )
+      {
+         // user passed '.' as Name
+         // we get current directory name
+         char buf[2048];
+         const char *cwd = getcwd(buf, 2048);
+         if( cwd )
+         {
+            SetFileName( buf ); // will be converted into a string
+         }
+         else
+         {
+            gdcmErrorMacro( "Path was too long to fit on 2048 bytes" );
+         }
+      }
+      NewMeta();
+      gdcmDebugMacro( "Parse directory and create the DicomDir : " 
+                         << GetFileName() );
+      ParseDirectory();
+   }
+   return true;
+}
+
+/**
+ * \brief  This predicate, based on hopefully reasonable heuristics,
+ *         decides whether or not the current document was properly parsed
+ *         and contains the mandatory information for being considered as
+ *         a well formed and usable DicomDir.
+ * @return true when Document is the one of a reasonable DicomDir,
+ *         false otherwise. 
+ */
+bool DicomDir::IsReadable()
+{
+   if ( Filetype == Unknown )
+   {
+      gdcmErrorMacro( "Wrong filetype for " << GetFileName());
+      return false;
+   }
+   if ( !MetaElems )
+   {
+      gdcmWarningMacro( "Meta Elements missing in DicomDir");
+      return false;
+   }
+   if ( Patients.size() <= 0 )
+   {
+      gdcmWarningMacro( "NO Patient in DicomDir");
+      return false;
+   }
+
+   return true;
+}
+
+/**
+ * \brief   adds *the* Meta to a partially created DICOMDIR
+ */  
+DicomDirMeta *DicomDir::NewMeta()
+{
+   if ( MetaElems )
+      delete MetaElems;
+
+   DocEntry *entry = GetFirstEntry();
+   if ( entry )
+   { 
+      MetaElems = new DicomDirMeta(true); // true = empty
+
+      entry = GetFirstEntry();
+      while( entry )
+      {
+         if ( dynamic_cast<SeqEntry *>(entry) )
+            break;
+
+         RemoveEntryNoDestroy(entry);
+         MetaElems->AddEntry(entry);
+
+         entry = GetFirstEntry();
+      }
+   }
+   else  // after root directory parsing
+   {
+      MetaElems = new DicomDirMeta(false); // false = not empty
+   }
+   MetaElems->SetSQItemNumber(0); // To avoid further missprinting
+   return MetaElems;  
+}
+
+/**
+ * \brief   adds a new Patient (with the basic elements) to a partially created
+ *          DICOMDIR
+ */
+DicomDirPatient *DicomDir::NewPatient()
+{
+   DicomDirPatient *p = new DicomDirPatient();
+   AddPatientToEnd( p );
+   return p;
+}
+
+/**
+ * \brief   Remove all Patients
+ */
+void DicomDir::ClearPatient()
+{
+   for(ListDicomDirPatient::iterator cc = Patients.begin();
+                                     cc!= Patients.end();
+                                   ++cc)
+   {
+      delete *cc;
+   }
+   Patients.clear();
+}
+
+/**
+ * \brief   Get the first entry while visiting the DicomDirPatients
+ * \return  The first DicomDirPatient if found, otherwhise NULL
+ */ 
+DicomDirPatient *DicomDir::GetFirstPatient()
+{
+   ItPatient = Patients.begin();
+   if ( ItPatient != Patients.end() )
+      return *ItPatient;
+   return NULL;
+}
+
+/**
+ * \brief   Get the next entry while visiting the DicomDirPatients
+ * \note : meaningfull only if GetFirstEntry already called
+ * \return  The next DicomDirPatient if found, otherwhise NULL
+ */
+DicomDirPatient *DicomDir::GetNextPatient()
+{
+   gdcmAssertMacro (ItPatient != Patients.end());
+
+   ++ItPatient;
+   if ( ItPatient != Patients.end() )
+      return *ItPatient;
+   return NULL;
+}
+
+/**
+ * \brief  fills the whole structure, starting from a root Directory
+ */
+void DicomDir::ParseDirectory()
+{
+   CreateDicomDirChainedList( GetFileName() );
+   CreateDicomDir();
+}
+
+void DicomDir::SetStartMethod( DicomDir::Method *method, void *arg )
+{
+   SetStartMethod(method,arg,NULL);
+}
+
+void DicomDir::SetProgressMethod( DicomDir::Method *method, void *arg )
+{
+   SetProgressMethod(method,arg,NULL);
+}
+
+void DicomDir::SetEndMethod( DicomDir::Method *method, void *arg )
+{
+   SetEndMethod(method,arg,NULL);
+}
+
+/**
+ * \brief   Set the start method to call when the parsing of the
+ *          directory starts.
+ * @param   method Method to call
+ * @param   arg    Argument to pass to the method
+ * @param   argDelete    Argument 
+ * \warning In python : the arg parameter isn't considered
+ */
+void DicomDir::SetStartMethod( DicomDir::Method *method, void *arg, 
+                               DicomDir::Method *argDelete )
+{
+   if ( StartArg && StartMethodArgDelete )
+   {
+      StartMethodArgDelete( StartArg );
+   }
+
+   StartMethod          = method;
+   StartArg             = arg;
+   StartMethodArgDelete = argDelete;
+}
+
+
+/**
+ * \brief   Set the progress method to call when the parsing of the
+ *          directory progress
+ * @param   method Method to call
+ * @param   arg    Argument to pass to the method
+ * @param   argDelete    Argument  
+ * \warning In python : the arg parameter isn't considered
+ */
+void DicomDir::SetProgressMethod( DicomDir::Method *method, void *arg, 
+                                  DicomDir::Method *argDelete )
+{
+   if ( ProgressArg && ProgressMethodArgDelete )
+   {
+      ProgressMethodArgDelete( ProgressArg );
+   }
+
+   ProgressMethod          = method;
+   ProgressArg             = arg;
+   ProgressMethodArgDelete = argDelete;
+}
+
+/**
+ * \brief   Set the end method to call when the parsing of the directory ends
+ * @param   method Method to call
+ * @param   arg    Argument to pass to the method
+ * @param   argDelete    Argument 
+ * \warning In python : the arg parameter isn't considered
+ */
+void DicomDir::SetEndMethod( DicomDir::Method *method, void *arg, 
+                             DicomDir::Method *argDelete )
+{
+   if ( EndArg && EndMethodArgDelete )
+   {
+      EndMethodArgDelete( EndArg );
+   }
+
+   EndMethod          = method;
+   EndArg             = arg;
+   EndMethodArgDelete = argDelete;
+}
+
+/**
+ * \brief   Set the method to delete the argument
+ *          The argument is destroyed when the method is changed or when the
+ *          class is destroyed
+ * @param   method Method to call to delete the argument
+ */
+void DicomDir::SetStartMethodArgDelete( DicomDir::Method *method ) 
+{
+   StartMethodArgDelete = method;
+}
+
+/**
+ * \brief   Set the method to delete the argument
+ *          The argument is destroyed when the method is changed or when the 
+ *          class is destroyed          
+ * @param   method Method to call to delete the argument
+ */
+void DicomDir::SetProgressMethodArgDelete( DicomDir::Method *method )
+{
+   ProgressMethodArgDelete = method;
+}
+
+/**
+ * \brief   Set the method to delete the argument
+ *          The argument is destroyed when the method is changed or when
+ *          the class is destroyed
+ * @param   method Method to call to delete the argument
+ */
+void DicomDir::SetEndMethodArgDelete( DicomDir::Method *method )
+{
+   EndMethodArgDelete = method;
+}
+
+/**
+ * \brief    writes on disc a DICOMDIR
+ * \ warning does NOT add the missing elements in the header :
+ *           it's up to the user doing it !
+ * @param  fileName file to be written to 
+ * @return false only when fail to open
+ */
+ 
+bool DicomDir::Write(std::string const &fileName) 
+{  
+   int i;
+   uint16_t sq[6] = { 0x0004, 0x1220, 0x5153, 0x0000, 0xffff, 0xffff };
+   uint16_t sqt[4]= { 0xfffe, 0xe0dd, 0x0000, 0x0000 };
+
+   std::ofstream *fp = new std::ofstream(fileName.c_str(),  
+                                         std::ios::out | std::ios::binary);
+   if ( !fp ) 
+   {
+      gdcmWarningMacro("Failed to open(write) File: " << fileName.c_str());
+      return false;
+   }
+
+   char filePreamble[128];
+   memset(filePreamble, 0, 128);
+   fp->write(filePreamble, 128);
+   binary_write( *fp, "DICM");
+ 
+   DicomDirMeta *ptrMeta = GetMeta();
+   ptrMeta->WriteContent(fp, ExplicitVR);
+   
+   // force writing 0004|1220 [SQ ], that CANNOT exist within DicomDirMeta
+   for(i=0;i<6;++i)
+   {
+      binary_write(*fp, sq[i]);
+   }
+        
+   for(ListDicomDirPatient::iterator cc  = Patients.begin();
+                                     cc != Patients.end();
+                                   ++cc )
+   {
+      (*cc)->WriteContent( fp, ExplicitVR );
+   }
+   
+   // force writing Sequence Delimitation Item
+   for(i=0;i<4;++i)
+   {
+      binary_write(*fp, sqt[i]);  // fffe e0dd 0000 0000 
+   }
+
+   fp->close();
+   delete fp;
+
+   return true;
+}
+
+/**
+ * \brief    Anonymize a DICOMDIR
+ * @return true 
+ */
+ 
+bool DicomDir::Anonymize() 
+{
+   ValEntry *v;
+   // Something clever to be found to forge the Patient names
+   itksys_ios::ostringstream s;
+   int i = 1;
+   for(ListDicomDirPatient::iterator cc = Patients.begin();
+                                     cc!= Patients.end();
+                                   ++cc)
+   {
+      s << i;
+      v = (*cc)->GetValEntry(0x0010, 0x0010) ; // Patient's Name
+      if (v)
+      {
+         v->SetValue(s.str());
+      }
+
+      v = (*cc)->GetValEntry(0x0010, 0x0020) ; // Patient ID
+      if (v)
+      {
+         v->SetValue(" ");
+      }
+
+      v = (*cc)->GetValEntry(0x0010, 0x0030) ; // Patient's BirthDate
+      if (v)
+      {
+         v->SetValue(" ");
+      }
+      s << "";
+      i++;
+   }
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+/**
+ * \brief create a Document-like chained list from a root Directory 
+ * @param path entry point of the tree-like structure
+ */
+void DicomDir::CreateDicomDirChainedList(std::string const &path)
+{
+   CallStartMethod();
+   DirList dirList(path,1); // gets recursively the file list
+   unsigned int count = 0;
+   VectDocument list;
+   File *f;
+
+   DirListType fileList = dirList.GetFilenames();
+
+   for( DirListType::iterator it  = fileList.begin();
+                              it != fileList.end();
+                              ++it )
+   {
+      Progress = (float)(count+1)/(float)fileList.size();
+      CallProgressMethod();
+      if ( Abort )
+      {
+         break;
+      }
+
+      f = new File( );
+      f->SetLoadMode(LoadMode); // we allow user not to load Sequences, 
+                                //        or Shadow groups, or ......
+      f->SetFileName( it->c_str() );
+   /*int res = */f->Load( );
+
+      if ( f->IsReadable() )
+      {
+         // Add the file to the chained list:
+         list.push_back(f);
+         gdcmDebugMacro( "Readable " << it->c_str() );
+       }
+       else
+       {
+          delete f;
+       }
+       count++;
+   }
+   // sorts Patient/Study/Serie/
+   std::sort(list.begin(), list.end(), DicomDir::HeaderLessThan );
+   
+   std::string tmp = dirList.GetDirName();      
+   //for each File of the chained list, add/update the Patient/Study/Serie/Image info
+   SetElements(tmp, list);
+   CallEndMethod();
+
+   for(VectDocument::iterator itDoc=list.begin();
+       itDoc!=list.end();
+       ++itDoc)
+   {
+      delete dynamic_cast<File *>(*itDoc);
+   }
+}
+
+/**
+ * \brief   CallStartMethod
+ */
+void DicomDir::CallStartMethod()
+{
+   Progress = 0.0f;
+   Abort    = false;
+   if ( StartMethod )
+   {
+      StartMethod( StartArg );
+   }
+}
+
+/**
+ * \brief   CallProgressMethod
+ */
+void DicomDir::CallProgressMethod()
+{
+   if ( ProgressMethod )
+   {
+      ProgressMethod( ProgressArg );
+   }
+}
+
+/**
+ * \brief   CallEndMethod
+ */
+void DicomDir::CallEndMethod()
+{
+   Progress = 1.0f;
+   if ( EndMethod )
+   {
+      EndMethod( EndArg );
+   }
+}
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \brief Sets all fields to NULL
+ */
+void DicomDir::Initialize()
+{
+   StartMethod             = NULL;
+   ProgressMethod          = NULL;
+   EndMethod               = NULL;
+   StartMethodArgDelete    = NULL;
+   ProgressMethodArgDelete = NULL;
+   EndMethodArgDelete      = NULL;
+   StartArg                = NULL;
+   ProgressArg             = NULL;
+   EndArg                  = NULL;
+
+   Progress = 0.0;
+   Abort = false;
+
+   MetaElems = NULL;   
+}
+
+/**
+ * \brief create a 'gdcm::DicomDir' from a DICOMDIR Header 
+ */
+void DicomDir::CreateDicomDir()
+{
+   // The SeqEntries of "Directory Record Sequence" are parsed. 
+   //  When a DicomDir tag ("PATIENT", "STUDY", "SERIE", "IMAGE") is found :
+   //  1 - we save the beginning iterator
+   //  2 - we continue to parse
+   //  3 - we find an other tag
+   //       + we create the object for the precedent tag
+   //       + loop to 1 -
+   gdcmDebugMacro("Create DicomDir");
+
+   // Directory record sequence
+   DocEntry *e = GetDocEntry(0x0004, 0x1220);
+   if ( !e )
+   {
+      gdcmWarningMacro( "No Directory Record Sequence (0004,1220) found");
+      return;         
+   }
+   
+   SeqEntry *s = dynamic_cast<SeqEntry *>(e);
+   if ( !s )
+   {
+      gdcmWarningMacro( "Element (0004,1220) is not a Sequence ?!?");
+      return;
+   }
+
+   NewMeta();
+   
+   DocEntry *d;
+   std::string v;
+   SQItem *si;
+
+   SQItem *tmpSI=s->GetFirstSQItem();
+   while(tmpSI)
+   {
+      d = tmpSI->GetDocEntry(0x0004, 0x1430); // Directory Record Type
+      if ( ValEntry* valEntry = dynamic_cast<ValEntry *>(d) )
+      {
+         v = valEntry->GetValue();
+      }
+      else
+      {
+         gdcmWarningMacro( "(0004,1430) not a ValEntry ?!?");
+         continue;
+      }
+
+      // A decent DICOMDIR has much more images than series,
+      // more series than studies, and so on.
+      // This is the right order to perform the tests
+
+      if ( v == "IMAGE " ) 
+      {
+         si = new DicomDirImage(true);
+         if ( !AddImageToEnd( static_cast<DicomDirImage *>(si)) )
+         {
+            delete si;
+            si = NULL;
+            gdcmErrorMacro( "Add AddImageToEnd failed");
+         }
+      }
+      else if ( v == "SERIES" )
+      {
+         si = new DicomDirSerie(true);
+         if ( !AddSerieToEnd( static_cast<DicomDirSerie *>(si)) )
+         {
+            delete si;
+            si = NULL;
+            gdcmErrorMacro( "Add AddSerieToEnd failed");
+         }
+      }
+      else if ( v == "VISIT " )
+      {
+         si = new DicomDirVisit(true);
+         if ( !AddVisitToEnd( static_cast<DicomDirVisit *>(si)) )
+         {
+            delete si;
+            si = NULL;
+            gdcmErrorMacro( "Add AddVisitToEnd failed");
+         }
+      }
+      else if ( v == "STUDY " )
+      {
+         si = new DicomDirStudy(true);
+         if ( !AddStudyToEnd( static_cast<DicomDirStudy *>(si)) )
+         {
+            delete si;
+            si = NULL;
+            gdcmErrorMacro( "Add AddStudyToEnd failed");
+         }
+      }
+      else if ( v == "PATIENT " )
+      {
+         si = new DicomDirPatient(true);
+         if ( !AddPatientToEnd( static_cast<DicomDirPatient *>(si)) )
+         {
+            delete si;
+            si = NULL;
+            gdcmErrorMacro( "Add PatientToEnd failed");
+         }
+      }
+      else
+      {
+         // It was neither a 'PATIENT', nor a 'STUDY', nor a 'SERIE',
+         // nor an 'IMAGE' SQItem. Skip to next item.
+         gdcmDebugMacro( " -------------------------------------------"
+         << "a non PATIENT/STUDY/SERIE/IMAGE SQItem was found : "
+         << v);
+
+        // FIXME : deal with other item types !
+        tmpSI=s->GetNextSQItem(); // To avoid infinite loop
+        continue;
+      }
+      if ( si )
+         //MoveSQItem(si,tmpSI); // Old code : Copies each Entry
+                                 //  -and then removes the source-
+         si->MoveObject(tmpSI);  // New code : Copies the List
+
+      tmpSI=s->GetNextSQItem();
+   }
+   ClearEntry();
+}
+
+/**
+ * \brief  AddPatientToEnd 
+ * @param   dd SQ Item to enqueue to the DicomPatient chained List
+ */
+bool DicomDir::AddPatientToEnd(DicomDirPatient *dd)
+{
+   Patients.push_back(dd);
+   return true;
+}
+
+/**
+ * \brief  AddStudyToEnd 
+ * @param   dd SQ Item to enqueue to the DicomDirStudy chained List
+ */
+bool DicomDir::AddStudyToEnd(DicomDirStudy *dd)
+{
+   if ( Patients.size() > 0 )
+   {
+      ListDicomDirPatient::iterator itp = Patients.end();
+      itp--;
+      (*itp)->AddStudy(dd);
+      return true;
+   }
+   return false;
+}
+
+/**
+ * \brief  AddSerieToEnd 
+ * @param   dd SQ Item to enqueue to the DicomDirSerie chained List
+ */
+bool DicomDir::AddSerieToEnd(DicomDirSerie *dd)
+{
+   if ( Patients.size() > 0 )
+   {
+      ListDicomDirPatient::iterator itp = Patients.end();
+      itp--;
+
+      DicomDirStudy *study = (*itp)->GetLastStudy();
+      if ( study )
+      {
+         study->AddSerie(dd);
+         return true;
+      }
+   }
+   return false;
+}
+
+/**
+ * \brief  AddVisitToEnd 
+ * @param   dd SQ Item to enqueue to the DicomDirVisit chained List
+ */
+bool DicomDir::AddVisitToEnd(DicomDirVisit *dd)
+{
+   if ( Patients.size() > 0 )
+   {
+      ListDicomDirPatient::iterator itp = Patients.end();
+      itp--;
+
+      DicomDirStudy *study = (*itp)->GetLastStudy();
+      if ( study )
+      {
+         study->AddVisit(dd);
+         return true;
+      }
+   }
+   return false;
+}
+/**
+ * \brief   AddImageToEnd
+ * @param   dd SQ Item to enqueue to the DicomDirImage chained List
+ */
+bool DicomDir::AddImageToEnd(DicomDirImage *dd)
+{
+   if ( Patients.size() > 0 )
+   {
+      ListDicomDirPatient::iterator itp = Patients.end();
+      itp--;
+
+      DicomDirStudy *study = (*itp)->GetLastStudy();
+      if ( study )
+      {
+         DicomDirSerie *serie = study->GetLastSerie();
+         if ( serie )
+         {
+            serie->AddImage(dd);
+            return true;
+         }
+      }
+   }
+   return false;
+}
+
+/**
+ * \brief  for each Header of the chained list, 
+ *         add/update the Patient/Study/Serie/Image info 
+ * @param   path path of the root directory
+ * @param   list chained list of Headers
+ */
+void DicomDir::SetElements(std::string const &path, VectDocument const &list)
+{
+   ClearEntry();
+   ClearPatient();
+
+   std::string patPrevName         = "", patPrevID  = "";
+   std::string studPrevInstanceUID = "", studPrevID = "";
+   std::string serPrevInstanceUID  = "", serPrevID  = "";
+
+   std::string patCurName,         patCurID;
+   std::string studCurInstanceUID, studCurID;
+   std::string serCurInstanceUID,  serCurID;
+
+   bool first = true;
+   for( VectDocument::const_iterator it = list.begin();
+                                     it != list.end(); 
+                                   ++it )
+   {
+      // get the current file characteristics
+      patCurName         = (*it)->GetEntryValue(0x0010,0x0010);
+      patCurID           = (*it)->GetEntryValue(0x0010,0x0011);
+      studCurInstanceUID = (*it)->GetEntryValue(0x0020,0x000d);
+      studCurID          = (*it)->GetEntryValue(0x0020,0x0010);
+      serCurInstanceUID  = (*it)->GetEntryValue(0x0020,0x000e);
+      serCurID           = (*it)->GetEntryValue(0x0020,0x0011);
+
+      if ( patCurName != patPrevName || patCurID != patPrevID || first )
+      {
+         SetElement(path, GDCM_DICOMDIR_PATIENT, *it);
+         first = true;
+      }
+
+      // if new Study, deal with 'STUDY' Elements   
+      if ( studCurInstanceUID != studPrevInstanceUID || studCurID != studPrevID 
+         || first )
+      {
+         SetElement(path, GDCM_DICOMDIR_STUDY, *it);
+         first = true;
+      }
+
+      // if new Serie, deal with 'SERIE' Elements   
+      if ( serCurInstanceUID != serPrevInstanceUID || serCurID != serPrevID
+         || first )
+      {
+         SetElement(path, GDCM_DICOMDIR_SERIE, *it);
+      }
+      
+      // Always Deal with 'IMAGE' Elements  
+      SetElement(path, GDCM_DICOMDIR_IMAGE, *it);
+
+      patPrevName         = patCurName;
+      patPrevID           = patCurID;
+      studPrevInstanceUID = studCurInstanceUID;
+      studPrevID          = studCurID;
+      serPrevInstanceUID  = serCurInstanceUID;
+      serPrevID           = serCurID;
+      first = false;
+   }
+}
+
+/**
+ * \brief   adds to the HTable 
+ *          the Entries (Dicom Elements) corresponding to the given type
+ * @param   path full path file name (only used when type = GDCM_DICOMDIR_IMAGE
+ * @param   type DicomDirObject type to create (GDCM_DICOMDIR_PATIENT,
+ *          GDCM_DICOMDIR_STUDY, GDCM_DICOMDIR_SERIE ...)
+ * @param   header Header of the current file
+ */
+void DicomDir::SetElement(std::string const &path, DicomDirType type,
+                          Document *header)
+{
+   ListDicomDirElem elemList;
+   ListDicomDirElem::const_iterator it;
+   uint16_t tmpGr, tmpEl;
+   DictEntry *dictEntry;
+   ValEntry *entry;
+   std::string val;
+   SQItem *si;
+
+   switch( type )
+   {
+      case GDCM_DICOMDIR_IMAGE:
+         elemList = Global::GetDicomDirElements()->GetDicomDirImageElements();
+         si = new DicomDirImage(true);
+         if ( !AddImageToEnd(static_cast<DicomDirImage *>(si)) )
+         {
+            delete si;
+            gdcmErrorMacro( "Add ImageToEnd failed");
+         }
+         break;
+      case GDCM_DICOMDIR_SERIE:
+         elemList = Global::GetDicomDirElements()->GetDicomDirSerieElements();
+         si = new DicomDirSerie(true);
+         if ( !AddSerieToEnd(static_cast<DicomDirSerie *>(si)) )
+         {
+            delete si;
+            gdcmErrorMacro( "Add SerieToEnd failed");
+         }
+         break;
+      case GDCM_DICOMDIR_STUDY:
+         elemList = Global::GetDicomDirElements()->GetDicomDirStudyElements();
+         si = new DicomDirStudy(true);
+         if ( !AddStudyToEnd(static_cast<DicomDirStudy *>(si)) )
+         {
+            delete si;
+            gdcmErrorMacro( "Add StudyToEnd failed");
+         }
+         break;
+      case GDCM_DICOMDIR_PATIENT:
+         elemList = Global::GetDicomDirElements()->GetDicomDirPatientElements();
+         si = new DicomDirPatient(true);
+         if ( !AddPatientToEnd(static_cast<DicomDirPatient *>(si)) )
+         {
+            delete si;
+            gdcmErrorMacro( "Add PatientToEnd failed");
+         }
+         break;
+      case GDCM_DICOMDIR_META:
+         elemList = Global::GetDicomDirElements()->GetDicomDirMetaElements();
+         si = new DicomDirMeta(true);
+         if ( MetaElems )
+         {
+            delete MetaElems;
+            gdcmErrorMacro( "MetaElements already exist, they will be destroyed");
+         }
+         MetaElems = static_cast<DicomDirMeta *>(si);
+         break;
+      default:
+         return;
+   }
+
+   // FIXME : troubles found when it's a SeqEntry
+
+   // removed all the seems-to-be-useless stuff about Referenced Image Sequence
+   // to avoid further troubles
+   // imageElem 0008 1140 "" // Referenced Image Sequence
+   // imageElem fffe e000 "" // 'no length' item : length to be set to 0xffffffff later
+   // imageElem 0008 1150 "" // Referenced SOP Class UID    : to be set/forged later
+   // imageElem 0008 1155 "" // Referenced SOP Instance UID : to be set/forged later
+   // imageElem fffe e00d "" // Item delimitation : length to be set to ZERO later
+ 
+   // for all the relevant elements found in their own spot of the DicomDir.dic
+   for( it = elemList.begin(); it != elemList.end(); ++it)
+   {
+      tmpGr     = it->Group;
+      tmpEl     = it->Elem;
+      dictEntry = GetPubDict()->GetEntry(tmpGr, tmpEl);
+
+      entry     = new ValEntry( dictEntry ); // Be sure it's never a BinEntry !
+
+      entry->SetOffset(0); // just to avoid further missprinting
+
+      if ( header )
+      {
+         // NULL when we Build Up (ex nihilo) a DICOMDIR
+         //   or when we add the META elems
+         val = header->GetEntryValue(tmpGr, tmpEl);
+      }
+      else
+      {
+         val = GDCM_UNFOUND;
+      }
+
+      if ( val == GDCM_UNFOUND) 
+      {
+         if ( tmpGr == 0x0004 && tmpEl == 0x1130 ) // File-set ID
+         {
+           // force to the *end* File Name
+           val = Util::GetName( path );
+         }
+         else if ( tmpGr == 0x0004 && tmpEl == 0x1500 ) // Only used for image
+         {
+            if ( header->GetFileName().substr(0, path.length()) != path )
+            {
+               gdcmWarningMacro( "The base path of file name is incorrect");
+               val = header->GetFileName();
+            }
+            else
+            {
+               val = &(header->GetFileName().c_str()[path.length()]);
+            }
+         }
+         else
+         {
+            val = it->Value;
+         }
+      }
+      else
+      {
+         if ( header->GetEntryLength(tmpGr,tmpEl) == 0 )
+            val = it->Value;
+      }
+
+      entry->SetValue( val ); // troubles expected when vr=SQ ...
+
+      if ( type == GDCM_DICOMDIR_META ) // fusible : should never print !
+      {
+         gdcmDebugMacro("GDCM_DICOMDIR_META ?!? should never print that");
+      }
+      si->AddEntry(entry);
+   }
+}
+
+/**
+ * \brief   Move the content of the source SQItem to the destination SQItem
+ *          Only DocEntry's are moved
+ * @param dst destination SQItem
+ * @param src source SQItem
+ */
+void DicomDir::MoveSQItem(DocEntrySet *dst, DocEntrySet *src)
+{ 
+   DocEntry *entry;
+// todo : rewrite the whole stuff, without using RemoveEntry an AddEntry,
+//        to save time
+   entry = src->GetFirstEntry();
+   while(entry)
+   {
+      src->RemoveEntryNoDestroy(entry);
+      dst->AddEntry(entry);
+      // we destroyed -> the current iterator is not longer valid
+      entry = src->GetFirstEntry();
+   }
+}
+
+/**
+ * \brief   compares two files
+ */
+bool DicomDir::HeaderLessThan(Document *header1, Document *header2)
+{
+   return *header1 < *header2;
+}
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief  Canonical Printer 
+ * @param   os ostream we want to print in
+ * @param indent Indentation string to be prepended during printing
+ */
+void DicomDir::Print(std::ostream &os, std::string const & )
+{
+   if ( MetaElems )
+   {
+      MetaElems->SetPrintLevel(PrintLevel);
+      MetaElems->Print(os);   
+   }   
+   for(ListDicomDirPatient::iterator cc  = Patients.begin();
+                                     cc != Patients.end();
+                                   ++cc)
+   {
+     (*cc)->SetPrintLevel(PrintLevel);
+     (*cc)->Print(os);
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDir.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDir.h
new file mode 100644
index 0000000000000000000000000000000000000000..ece08e18fc8ccc54daef5ad80ffa5d539535d862
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDir.h
@@ -0,0 +1,200 @@
+/*=========================================================================
+  
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDir.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+  
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+  
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+  
+=========================================================================*/
+
+#ifndef GDCMDICOMDIR_H
+#define GDCMDICOMDIR_H
+
+#include "gdcmDocument.h"
+#include "gdcmDebug.h"
+
+#include <list>
+#include <vector>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+class DicomDirPatient;
+class DicomDirMeta;
+class DicomDirElement;
+class DicomDirStudy;
+class DicomDirSerie;
+class DicomDirVisit;
+class DicomDirImage;
+class SQItem;
+
+typedef std::list<DicomDirPatient *> ListDicomDirPatient;
+typedef std::vector<Document *> VectDocument;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief   DicomDir defines an object representing a DICOMDIR in memory
+ *  as a tree-like structure DicomDirPatient 
+ *                            -> DicomDirStudy 
+ *                                -> DicomDirSerie
+ *                                    -> DicomDirImage
+ */
+class GDCM_EXPORT DicomDir: public Document
+{
+public:
+   typedef void Method(void*);
+
+   DicomDir(); 
+   GDCM_LEGACY( DicomDir(std::string const &filename, bool parseDir = false) ); 
+   ~DicomDir();
+
+   GDCM_LEGACY( bool Load(std::string const &filename) );
+   bool Load( );
+   void Print(std::ostream &os = std::cout, std::string const &indent = "" );
+   
+   /// Sets the root Directory name to parse, recursively
+   void SetDirectoryName(std::string const &dirName) 
+        { ParseDir = true; if (Filename != dirName)
+                               Filename = dirName, IsDocumentModified = true; }
+   /// Accessor to \ref Filename
+   virtual void SetFileName(std::string const &fileName) 
+                   { ParseDir = false; if (Filename != fileName)
+                              Filename = fileName, IsDocumentModified = true;}
+
+   /// DEPRECATED : use SetDirectoryName
+   GDCM_LEGACY( void SetParseDir(bool parseDir) );
+   
+   // Informations contained in the parser
+   virtual bool IsReadable();
+
+   // Meta
+   DicomDirMeta *NewMeta();
+   /// Returns a pointer to the DicomDirMeta for this DICOMDIR. 
+   DicomDirMeta *GetMeta() { return MetaElems; }
+
+   // Patients
+   DicomDirPatient *NewPatient();
+   void ClearPatient();
+
+   DicomDirPatient *GetFirstPatient();
+   DicomDirPatient *GetNextPatient();
+
+   // Parsing
+   void ParseDirectory();
+
+   // Note: the DicomDir:: namespace prefix is needed by Swig in the 
+   //       following method declarations. Refer to gdcmPython/gdcm.i
+   //       for the reasons of this unnecessary notation at C++ level.
+   void SetStartMethod(    DicomDir::Method *method,
+                           void *arg = NULL );
+   void SetProgressMethod( DicomDir::Method *method,
+                           void *arg = NULL );
+   void SetEndMethod(      DicomDir::Method *method,
+                           void *arg = NULL );
+   // Note: replace DicomDir::Method *method to void(*method)(void *) to
+   //       avoid wrapping problems with the typemap conversions
+   void SetStartMethod(    void(*method)(void *), // DicomDir::Method *method
+                           void *arg,
+                           void(*argDelete)(void *));
+   void SetProgressMethod( void(*method)(void *), // DicomDir::Method *method
+                           void *arg,
+                           void(*argDelete)(void *));
+   void SetEndMethod(      void(*method)(void *), // DicomDir::Method *method
+                           void *arg, 
+                           void(*argDelete)(void *));
+   void SetStartMethodArgDelete   ( DicomDir::Method *method );
+   void SetProgressMethodArgDelete( DicomDir::Method *method );
+   void SetEndMethodArgDelete     ( DicomDir::Method *method );
+
+   /// GetProgress GetProgress
+   float GetProgress() const { return Progress; }
+   /// AbortProgress AbortProgress
+   void  AbortProgress() { Abort = true; }
+   /// IsAborted IsAborted
+   bool  IsAborted() { return Abort; }
+
+   // Write
+   bool Write(std::string const &fileName);
+
+   bool Anonymize();
+
+   /// Types of the DicomDirObject within the DicomDir
+   typedef enum
+   {
+      GDCM_DICOMDIR_NONE,
+      GDCM_DICOMDIR_META,
+      GDCM_DICOMDIR_PATIENT,
+      GDCM_DICOMDIR_STUDY,
+      GDCM_DICOMDIR_SERIE,
+      GDCM_DICOMDIR_VISIT,
+      GDCM_DICOMDIR_IMAGE
+   } DicomDirType;
+   
+protected:
+   void CreateDicomDirChainedList(std::string const &path);
+   void CallStartMethod();
+   void CallProgressMethod();
+   void CallEndMethod();
+
+private:
+   void Initialize();
+   void CreateDicomDir();
+   bool DoTheLoadingJob();
+   bool AddPatientToEnd(DicomDirPatient *dd);
+   bool AddStudyToEnd  (DicomDirStudy *dd);
+   bool AddSerieToEnd  (DicomDirSerie *dd);
+   bool AddVisitToEnd  (DicomDirVisit *dd);
+   bool AddImageToEnd  (DicomDirImage *dd);
+
+   void SetElements(std::string const &path, VectDocument const &list);
+   void SetElement (std::string const &path, DicomDirType type,
+                    Document *header);
+   void MoveSQItem(DocEntrySet *dst, DocEntrySet *src);
+
+   static bool HeaderLessThan(Document *header1, Document *header2);
+   
+// Variables
+
+   /// Pointer on *the* DicomDirObject 'DicomDirMeta Elements'
+   DicomDirMeta *MetaElems;
+
+   /// Chained list of DicomDirPatient (to be exploited hierarchicaly) 
+   ListDicomDirPatient Patients;
+   ListDicomDirPatient::iterator ItPatient;
+
+   /// pointer to the initialisation method for any progress bar   
+   Method *StartMethod;
+   /// pointer to the incrementation method for any progress bar
+   Method *ProgressMethod;
+   /// pointer to the termination method for any progress bar
+   Method *EndMethod;
+   /// pointer to the ??? method for any progress bar   
+   Method *StartMethodArgDelete;
+   /// pointer to the ??? method for any progress bar
+   Method* ProgressMethodArgDelete;
+   /// pointer to the ??? method for any progress bar
+   Method *EndMethodArgDelete;
+   /// pointer to the ??? for any progress bar   
+   void *StartArg;
+   /// pointer to the ??? for any progress bar
+   void *ProgressArg;
+   /// pointer to the ??? for any progress bar   
+   void *EndArg;
+   /// value of the ??? for any progress bar
+   float Progress;
+   /// value of the ??? for any progress bar   
+   bool Abort;
+   bool ParseDir;
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirElement.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirElement.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..06336ab09cc26dee8f594173a502aa2efbe708ad
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirElement.cxx
@@ -0,0 +1,219 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirElement.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.7 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDicomDirElement.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+#include "gdcmDictSet.h"
+
+#include <fstream>
+#include <iostream>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/// \brief auto generate function, to fill up the default elements for 
+///        a DICOMDIR, if relevant file is not found on user's disk
+void FillDefaultDIRDict(DicomDirElement *dde);
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   constructor : populates the chained lists 
+ *          from the file 'Dicts/DicomDir.dic'
+ */
+DicomDirElement::DicomDirElement()
+{
+   std::string filename = DictSet::BuildDictPath() + DICT_ELEM;
+   std::ifstream from(filename.c_str());
+   if ( !from )
+   {
+      gdcmWarningMacro( "Can't open DicomDirElement dictionary" 
+                        << filename.c_str());
+      FillDefaultDIRDict( this );
+   }
+   else
+   {
+      char buff[1024];
+      std::string strType;
+      Element elem;
+      DicomDirType type;
+
+      while (!from.eof())
+      {
+         from >> std::ws;
+         from.getline(buff, 1024, ' ');
+         strType = buff;
+
+         if ( strType == "imageElem" )
+            type = DD_IMAGE;
+         else if ( strType == "serieElem" )
+            type = DD_SERIE;
+         else if ( strType == "studyElem" )
+            type = DD_STUDY;
+         else if ( strType == "patientElem" )
+            type = DD_PATIENT;
+         else if ( strType == "metaElem" )
+            type = DD_META;
+         else
+         {
+            gdcmWarningMacro("Unknown type (" << strType 
+                             << ") found in the file : "
+                             << filename.c_str());
+            type = DD_UNKNOWN;
+         }
+
+         if ( type!=DD_UNKNOWN )
+         {
+            from >> std::hex >> elem.Group >> elem.Elem;
+
+            from >> std::ws;
+            from.getline(buff, 1024, '"');
+            from >> std::ws;
+            from.getline(buff, 1024, '"');
+            elem.Value = buff;
+
+            AddEntry(type, elem);
+         }
+         from.getline(buff, 1024, '\n');
+      }
+      from.close();
+   }
+}
+
+/**
+ * \brief   canonical destructor 
+ */
+DicomDirElement::~DicomDirElement()
+{
+   DicomDirMetaList.clear();
+   DicomDirPatientList.clear();
+   DicomDirStudyList.clear();
+   DicomDirSerieList.clear();
+   DicomDirImageList.clear();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief Add an entry to one of the DicomDir Elements 
+ *        (Patient, Study, Serie, Image)
+ * @param type Element type (DD_PATIENT, DD_STUDY, DD_SERIE, DD_IMAGE) 
+ * @param elem elem
+ */
+bool DicomDirElement::AddEntry(DicomDirType type, Element const &elem)
+{
+   switch( type )
+   {
+      case DD_IMAGE :
+         DicomDirImageList.push_back(elem);
+         break;
+      case DD_SERIE :
+         DicomDirSerieList.push_back(elem);
+         break;
+      case DD_STUDY :
+         DicomDirStudyList.push_back(elem);
+         break;
+      case DD_PATIENT :
+         DicomDirPatientList.push_back(elem);
+         break;
+      case DD_META :
+         DicomDirMetaList.push_back(elem);
+         break;
+      default :
+         return false;
+   }
+   return true;
+}
+
+/**
+ * \brief Add an entry to one of the DicomDir Elements 
+ *        (Patient, Study, Serie, Image)
+ * @param type Element type (DD_PATIENT, DD_STUDY, DD_SERIE, DD_IMAGE) 
+ * @param group  Group number of the entry to be added
+ * @param elem Element number of the entry to be added
+ */
+void DicomDirElement::AddDicomDirElement(DicomDirType type,
+                                         uint16_t group, uint16_t elem)
+{
+   Element el;
+   el.Group = group;
+   el.Elem  = elem;
+   el.Value = "";
+   AddEntry(type, el);
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Print all
+ * @param   os The output stream to be written to.
+ */
+void DicomDirElement::Print(std::ostream &os,std::string const &)
+{
+   itksys_ios::ostringstream s;
+   std::list<Element>::iterator it;
+   //char greltag[10];  //group element tag
+   TagKey greltag;
+
+   s << "Meta Elements :"<<std::endl;
+   for (it = DicomDirMetaList.begin(); it != DicomDirMetaList.end(); ++it)
+   {
+      greltag = DictEntry::TranslateToKey(it->Group,it->Elem);
+      s << "   (" << greltag << ") = " << it->Value << std::endl;
+   }
+
+   s << "Patient Elements :"<<std::endl;
+   for (it = DicomDirPatientList.begin(); it != DicomDirPatientList.end(); ++it)
+   {
+      greltag = DictEntry::TranslateToKey(it->Group,it->Elem);
+      s << "   (" << greltag << ") = " << it->Value << std::endl;
+   }
+
+   s << "Study Elements :"<<std::endl;
+   for (it = DicomDirStudyList.begin(); it != DicomDirStudyList.end(); ++it)
+   {
+      greltag = DictEntry::TranslateToKey(it->Group, it->Elem);
+      s << "   (" << greltag << ") = " << it->Value << std::endl;
+   }
+
+   s << "Serie Elements :"<<std::endl;
+   for (it = DicomDirSerieList.begin(); it != DicomDirSerieList.end(); ++it)
+   {
+      greltag = DictEntry::TranslateToKey( it->Group, it->Elem);
+      s << "   (" << greltag << ") = " << it->Value << std::endl;
+   }
+
+   s << "Image Elements :"<<std::endl;
+   for (it = DicomDirImageList.begin(); it != DicomDirImageList.end(); ++it)
+   {
+      greltag = DictEntry::TranslateToKey(it->Group, it->Elem);
+      s << "   (" << greltag << ") = " << it->Value << std::endl;
+   }
+
+   os << s.str();
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirElement.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirElement.h
new file mode 100644
index 0000000000000000000000000000000000000000..0870e29a158762a9c6a3929aab8c2c96a2fae09e
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirElement.h
@@ -0,0 +1,145 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirElement.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICOMDIRELEMENT_H
+#define GDCMDICOMDIRELEMENT_H
+
+#include "gdcmCommon.h"
+
+#include <list>
+#include <iostream>
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+
+typedef std::list<Element> ListDicomDirElem;
+typedef std::list<Element> ListDicomDirMetaElem;
+typedef std::list<Element> ListDicomDirPatientElem;
+typedef std::list<Element> ListDicomDirStudyElem;
+typedef std::list<Element> ListDicomDirVisitElem;
+typedef std::list<Element> ListDicomDirSerieElem;
+typedef std::list<Element> ListDicomDirImageElem;
+
+// For future use (Full DICOMDIR)
+
+/*
+typedef std::list<Element> ListDicomDirResultElem;
+typedef std::list<Element> ListDicomDirStudyComponentElem;
+
+typedef std::list<Element> ListDicomDirOverlayElem;
+typedef std::list<Element> ListDicomDirModalityLutElem;
+typedef std::list<Element> ListDicomDirModalityLutElem;
+typedef std::list<Element> ListDicomDirCurveElem;
+typedef std::list<Element> ListDicomDirStoredPrintElem;
+typedef std::list<Element> ListDicomDirRtDoseElem;
+typedef std::list<Element> ListDicomDirRtStructureSetElem;
+typedef std::list<Element> ListDicomDirRtPlanElem;
+typedef std::list<Element> ListDicomDirRtTreatRecordElem;
+typedef std::list<Element> ListDicomDirPresentationElem;
+typedef std::list<Element> ListDicomDirSrDocumentElem;
+typedef std::list<Element> ListDicomDirKeyObjectDocElem;
+typedef std::list<Element> ListDicomDirSpectroscopyElem;
+typedef std::list<Element> ListDicomDirRawDataElem;
+typedef std::list<Element> ListDicomDirRegistrationElem;
+typedef std::list<Element> ListDicomDirFiducialElem;
+*/
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief   Represents elements contained in a DicomDir class
+ *          for the chained lists from the file 'Dicts/DicomDir.dic'
+ */
+class GDCM_EXPORT DicomDirElement
+{
+public:
+   DicomDirElement();
+   ~DicomDirElement();
+
+   /**
+    * \brief   canonical Printer 
+    */ 
+   void Print(std::ostream &os = std::cout, 
+              std::string const &indent = "" );
+
+   /**
+    * \brief   returns a reference to the chained List 
+    *          related to the META Elements of a DICOMDIR.
+    */
+   ListDicomDirMetaElem const &GetDicomDirMetaElements() const
+      { return DicomDirMetaList; }
+
+   /**
+    * \brief   returns a reference to the chained List 
+    *          related to the PATIENT Elements of a DICOMDIR.
+    */      
+   ListDicomDirPatientElem const &GetDicomDirPatientElements() const
+      { return DicomDirPatientList; }
+
+   /**
+    * \brief   returns a reference to the chained List 
+    *          related to the STUDY Elements of a DICOMDIR.
+    */      
+   ListDicomDirStudyElem const &GetDicomDirStudyElements() const
+      { return DicomDirStudyList; }
+
+   /**
+    * \brief   returns a reference to the chained List 
+    *          related to the VISIT Elements of a DICOMDIR.
+    */      
+   ListDicomDirVisitElem const &GetDicomDirVisitElements() const
+      { return DicomDirVisitList; }
+   /**
+    * \brief   returns a reference to the chained List 
+    *          related to the SERIE Elements of a DICOMDIR.
+    */
+   ListDicomDirSerieElem const &GetDicomDirSerieElements() const
+      { return DicomDirSerieList; }
+
+   /**
+    * \brief   returns a reference to the chained List 
+    *          related to the IMAGE Elements of a DICOMDIR.
+    */
+   ListDicomDirImageElem const &GetDicomDirImageElements() const
+      { return DicomDirImageList; }
+
+   // Public method to add an element
+   bool AddEntry(DicomDirType type, Element const &elem);
+
+   // Only one instance of ddElem 
+   void AddDicomDirElement(DicomDirType type,
+                           uint16_t group, uint16_t elem);
+
+private:
+   /// Elements chained list, related to the MetaElements of DICOMDIR
+   ListDicomDirMetaElem    DicomDirMetaList;
+   /// Elements chained list, related to the PatientElements of DICOMDIR
+   ListDicomDirPatientElem DicomDirPatientList;
+   /// Elements chained list, related to the StudyElements of DICOMDIR
+   ListDicomDirStudyElem   DicomDirStudyList;
+   /// Elements chained list, related to the VisitElements of DICOMDIR
+   ListDicomDirVisitElem   DicomDirVisitList;
+   /// Elements chained list, related to the SerieElements of DICOMDIR
+   ListDicomDirSerieElem   DicomDirSerieList;
+   /// Elements chained list, related to the ImageElements of DICOMDIR
+   ListDicomDirImageElem   DicomDirImageList;
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirImage.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirImage.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..df550efb8d42fa630ce2403e8caa45aee5d221cd
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirImage.cxx
@@ -0,0 +1,86 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirImage.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDicomDirImage.h"
+#include "gdcmValEntry.h"
+#include "gdcmGlobal.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief  Constructor 
+ * \note End user must use : DicomDirSerie::NewImage()
+ */
+DicomDirImage::DicomDirImage(bool empty):
+   DicomDirObject()
+{
+   if ( !empty )
+   {
+      ListDicomDirImageElem const &elemList = 
+         Global::GetDicomDirElements()->GetDicomDirImageElements();
+      FillObject(elemList);
+   }
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+DicomDirImage::~DicomDirImage() 
+{
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Prints the Object
+ * @param os ostream to write to
+ * @param indent Indentation string to be prepended during printing
+ * @return
+ */ 
+void DicomDirImage::Print(std::ostream &os, std::string const & )
+{
+   os << "IMAGE : ";
+   for(ListDocEntry::iterator i = DocEntries.begin();
+                              i!= DocEntries.end();
+                              ++i)
+   {
+      if ( (*i)->GetGroup() == 0x0004 && (*i)->GetElement() == 0x1500 )
+      {
+         if( dynamic_cast<ValEntry *>(*i) )
+            os << (dynamic_cast<ValEntry *>(*i))->GetValue();
+      }
+   }
+   os << std::endl;
+
+   DicomDirObject::Print(os);
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirImage.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirImage.h
new file mode 100644
index 0000000000000000000000000000000000000000..148e1d1eeccb8e2eea3d7c28726ddd492f82a06b
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirImage.h
@@ -0,0 +1,41 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirImage.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICOMIMAGE_H
+#define GDCMDICOMIMAGE_H
+
+#include "gdcmDicomDirObject.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/**
+ * \brief   describes an IMAGE within a SERIE
+ * (DicomDirSerie) of a given DICOMDIR (DicomDir)
+ */
+ class GDCM_EXPORT DicomDirImage : public DicomDirObject
+{
+public:
+   DicomDirImage(bool empty=false); 
+   ~DicomDirImage();
+
+   void Print(std::ostream &os = std::cout, std::string const &indent = "" );
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirMeta.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirMeta.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..965f4920c90355834bfcaf24d6ed3a782d813e91
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirMeta.cxx
@@ -0,0 +1,95 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirMeta.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDicomDirMeta.h"
+#include "gdcmDocument.h"
+#include "gdcmDocEntry.h"
+#include "gdcmGlobal.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief  Constructor
+ */ 
+DicomDirMeta::DicomDirMeta(bool empty):
+   DicomDirObject()
+{
+   if ( !empty )
+   {
+      ListDicomDirStudyElem const &elemList = 
+         Global::GetDicomDirElements()->GetDicomDirMetaElements();
+      FillObject(elemList);
+   }
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+DicomDirMeta::~DicomDirMeta() 
+{
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Writes the Meta Elements
+ * @param fp ofstream to write to
+ * @param filetype type of the file (ACR, ImplicitVR, ExplicitVR, ...)
+ * @return
+ */ 
+void DicomDirMeta::WriteContent(std::ofstream *fp, FileType filetype)
+{
+  for (ListDocEntry::iterator i = DocEntries.begin();  
+                              i != DocEntries.end();
+                              ++i)
+   {
+      (*i)->WriteContent(fp, filetype);
+   }
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Prints the Meta Elements
+ * @param os ostream to write to 
+ * @param indent Indentation string to be prepended during printing
+ */ 
+void DicomDirMeta::Print(std::ostream &os, std::string const & )
+{
+   os << "META" << std::endl;
+   // warning : META doesn't behave exactly like a Objet 
+   for (ListDocEntry::iterator i = DocEntries.begin();
+        i != DocEntries.end();
+        ++i)
+   {
+      (*i)->SetPrintLevel(PrintLevel);
+      (*i)->Print();
+      os << std::endl;
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirMeta.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirMeta.h
new file mode 100644
index 0000000000000000000000000000000000000000..7b62c02185f6ba9bbc24ff61af040f024ad66f2d
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirMeta.h
@@ -0,0 +1,42 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirMeta.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICOMDIRMETA_H
+#define GDCMDICOMDIRMETA_H
+
+#include "gdcmDicomDirObject.h"
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief   Meta Elements (group 0002) of a DicomDir
+ */
+class GDCM_EXPORT DicomDirMeta : public DicomDirObject 
+{
+public:
+   DicomDirMeta(bool empty=false); 
+   ~DicomDirMeta();
+
+   virtual void Print(std::ostream &os = std::cout, std::string const &indent = "" );
+   virtual void WriteContent(std::ofstream *fp, FileType t);
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirObject.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirObject.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ce751cb0a0fe9c125406275ff83d028204740a0f
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirObject.cxx
@@ -0,0 +1,85 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirObject.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDicomDirObject.h"
+#include "gdcmGlobal.h"
+#include "gdcmDebug.h"
+#include "gdcmValEntry.h"
+#include "gdcmDictSet.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/**
+ * \brief  Constructor 
+ *          
+ * @param depth Sequence depth level
+ */
+  
+DicomDirObject::DicomDirObject(int depth) 
+          : SQItem (depth)
+{
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+DicomDirObject::~DicomDirObject()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+//-----------------------------------------------------------------------------
+// Protected
+/**
+ * \brief   add the 'Object' related Dicom Elements to the listEntries
+ *          of a partially created DICOMDIR
+ * @param elemList Element List to add at the right place
+ */
+void DicomDirObject::FillObject(ListDicomDirMetaElem const &elemList)
+{
+  // FillObject fills up the SQItem that will be connected to the right place
+   ListDicomDirMetaElem::const_iterator it;
+   uint16_t tmpGr,tmpEl;
+   DictEntry *dictEntry;
+   ValEntry *entry;
+      
+   // for all the Elements found in they own part of the DicomDir dict.     
+   for(it = elemList.begin(); it != elemList.end(); ++it)
+   {
+      tmpGr = it->Group;
+      tmpEl = it->Elem;
+      dictEntry = Global::GetDicts()->GetDefaultPubDict()->GetEntry(tmpGr,tmpEl);
+      entry = new ValEntry(dictEntry);
+      entry->SetOffset(0); // just to avoid further missprinting
+      entry->SetValue(it->Value);
+
+      AddEntry(entry);
+   }
+}  
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirObject.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirObject.h
new file mode 100644
index 0000000000000000000000000000000000000000..42c0870ed566710e656e3d06d5c608c1cb14fe82
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirObject.h
@@ -0,0 +1,56 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirObject.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICOMDIROBJECT_H
+#define GDCMDICOMDIROBJECT_H
+
+#include "gdcmSQItem.h"
+#include "gdcmDicomDirElement.h"
+
+#include <string>
+#include <list>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+class DicomDirObject;
+
+//-----------------------------------------------------------------------------
+typedef std::list<DicomDirObject *> ListContent;
+//-----------------------------------------------------------------------------
+/**
+ * \brief   Parent object for DicomDirPatient, DicomDirStudy, 
+ *                            DicomDirSerie, DicomDirImage, of a DicomDir
+ */
+class GDCM_EXPORT DicomDirObject : public SQItem
+{
+public:
+
+protected:
+   // Constructor and destructor are protected to avoid end user to
+   // instanciate from this class. 
+   DicomDirObject(int depth = 1);
+   ~DicomDirObject();
+
+   void FillObject(ListDicomDirMetaElem const &elemList);
+
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirPatient.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirPatient.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..73521cb699c1f534ed070d39a6e0fbbf6f97bc7b
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirPatient.cxx
@@ -0,0 +1,167 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirPatient.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDicomDirPatient.h"
+#include "gdcmDicomDirElement.h"
+#include "gdcmGlobal.h"
+#include "gdcmDicomDirStudy.h"
+#include "gdcmSQItem.h"
+#include "gdcmDebug.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor
+ * \note End user must use : DicomDir::NewPatient()
+ */
+DicomDirPatient::DicomDirPatient(bool empty)
+                :DicomDirObject()
+{
+   if ( !empty )
+   {
+      ListDicomDirStudyElem const &elemList = 
+         Global::GetDicomDirElements()->GetDicomDirPatientElements();
+      FillObject(elemList);
+   }
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+DicomDirPatient::~DicomDirPatient() 
+{
+   ClearStudy();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Writes the Object
+ * @param fp ofstream to write to
+ * @param t Type of the File (explicit VR, implicitVR, ...) 
+ */ 
+void DicomDirPatient::WriteContent(std::ofstream *fp, FileType t)
+{
+   DicomDirObject::WriteContent(fp, t);
+
+   for(ListDicomDirStudy::iterator cc = Studies.begin();
+                                   cc!= Studies.end();
+                                 ++cc )
+   {
+      (*cc)->WriteContent( fp, t );
+   }
+}
+
+/**
+ * \brief   adds a new Patient at the beginning of the PatientList
+ *          of a partially created DICOMDIR
+ */
+DicomDirStudy* DicomDirPatient::NewStudy()
+{
+   DicomDirStudy *st = new DicomDirStudy();
+   Studies.push_back(st);
+   return st; 
+}   
+
+/**
+ * \brief  Remove all studies in the patient 
+ */
+void DicomDirPatient::ClearStudy()
+{
+   for(ListDicomDirStudy::const_iterator cc = Studies.begin();
+                                         cc != Studies.end(); 
+                                       ++cc )
+   {
+      delete *cc;
+   }
+   Studies.clear();
+}
+
+/**
+ * \brief   Get the first entry while visiting the DicomDirStudy
+ * \return  The first DicomDirStudy if found, otherwhise NULL
+ */ 
+DicomDirStudy *DicomDirPatient::GetFirstStudy()
+{
+   ItStudy = Studies.begin();
+   if (ItStudy != Studies.end())
+      return *ItStudy;
+   return NULL;
+}
+
+/**
+ * \brief   Get the next entry while visiting the DicomDirStudies
+ * \note : meaningfull only if GetFirstEntry already called
+ * \return  The next DicomDirStudies if found, otherwhise NULL
+ */
+DicomDirStudy *DicomDirPatient::GetNextStudy()
+{
+   gdcmAssertMacro (ItStudy != Studies.end())
+
+   ++ItStudy;
+   if (ItStudy != Studies.end())
+      return *ItStudy;
+   return NULL;
+}
+
+/**
+ * \brief   Get the first entry while visiting the DicomDirStudy
+ * \return  The first DicomDirStudy if found, otherwhise NULL
+ */ 
+DicomDirStudy *DicomDirPatient::GetLastStudy()
+{
+   ItStudy = Studies.end();
+   if (ItStudy != Studies.begin())
+   {
+      --ItStudy;
+      return *ItStudy;
+   }
+   return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Prints the Object
+ * @param os ostream to write to 
+ * @param indent Indentation string to be prepended during printing
+ */ 
+void DicomDirPatient::Print(std::ostream &os, std::string const & )
+{
+   os << "PATIENT" << std::endl;
+   DicomDirObject::Print(os);
+
+   for(ListDicomDirStudy::const_iterator cc = Studies.begin();
+                                         cc != Studies.end(); 
+                                       ++cc )
+   {
+      (*cc)->SetPrintLevel(PrintLevel);
+      (*cc)->Print(os);
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirPatient.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirPatient.h
new file mode 100644
index 0000000000000000000000000000000000000000..318f718c407532d6a7ea4ebc6eecec29ffdb04dc
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirPatient.h
@@ -0,0 +1,65 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirPatient.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMPATIENT_H
+#define GDCMPATIENT_H
+
+#include "gdcmDicomDirObject.h"
+
+namespace gdcm 
+{
+class DicomDirStudy;
+
+//-----------------------------------------------------------------------------
+typedef std::list<DicomDirStudy*> ListDicomDirStudy;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief   describes a PATIENT within a DICOMDIR (DicomDir)
+ */
+
+class GDCM_EXPORT DicomDirPatient : public DicomDirObject 
+{
+public:
+   DicomDirPatient(bool empty=false); 
+   ~DicomDirPatient();
+
+   void Print(std::ostream &os = std::cout, std::string const &indent = "" );
+   void WriteContent(std::ofstream *fp, FileType t);
+  
+   // Patient methods
+   /// \brief Adds a new gdcmDicomDirStudy to the Patient
+   void AddStudy(DicomDirStudy *obj) { Studies.push_back(obj); }
+   DicomDirStudy *NewStudy(); 
+   void ClearStudy();
+
+   DicomDirStudy *GetFirstStudy();
+   DicomDirStudy *GetNextStudy();
+   DicomDirStudy *GetLastStudy();
+
+private:
+
+   /// chained list of DicomDirStudy  (to be exploited hierarchicaly)
+   ListDicomDirStudy Studies;
+   /// iterator on the DicomDirStudies of the current DicomDirPatient
+   ListDicomDirStudy::iterator ItStudy;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirSerie.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirSerie.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..cada8bde6917129aeaf978dd48deae572beaa095
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirSerie.cxx
@@ -0,0 +1,151 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirSerie.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDicomDirSerie.h"
+#include "gdcmDicomDirElement.h"
+#include "gdcmDicomDirImage.h"
+#include "gdcmGlobal.h"
+#include "gdcmDebug.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief  Constructor
+ * \note End user must use : DicomDirStudy::NewSerie() 
+ */
+DicomDirSerie::DicomDirSerie(bool empty):
+   DicomDirObject()
+{
+   if ( !empty )
+   {
+      ListDicomDirSerieElem const &elemList = 
+         Global::GetDicomDirElements()->GetDicomDirSerieElements();   
+      FillObject(elemList);
+   }
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+DicomDirSerie::~DicomDirSerie() 
+{
+   ClearImage();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Writes the Object
+ * @param fp ofstream to write to
+ * @param t Type of the File (explicit VR, implicitVR, ...)
+ */ 
+void DicomDirSerie::WriteContent(std::ofstream *fp, FileType t)
+{
+   DicomDirObject::WriteContent(fp, t);
+
+   for(ListDicomDirImage::iterator cc = Images.begin();
+                                   cc!= Images.end();
+                                 ++cc )
+   {
+      (*cc)->WriteContent( fp, t );
+   }
+}
+
+/**
+ * \brief   adds a new Image (with the basic elements) to a partially created 
+ *          DICOMDIR
+ */
+DicomDirImage *DicomDirSerie::NewImage()
+{
+   DicomDirImage *st = new DicomDirImage();
+   Images.push_back(st);
+   return st;   
+}
+
+/**
+ * \brief  Remove all images in the serie 
+ */
+void DicomDirSerie::ClearImage()
+{
+   for(ListDicomDirImage::iterator cc = Images.begin();
+                                   cc != Images.end();
+                                   ++cc)
+   {
+      delete *cc;
+   }
+   Images.clear();
+}
+
+/**
+ * \brief   Get the first entry while visiting the DicomDirImage
+ * \return  The first DicomDirImage if DicomDirserie not empty, otherwhise NULL
+ */
+DicomDirImage *DicomDirSerie::GetFirstImage()
+{
+   ItImage = Images.begin();
+   if (ItImage != Images.end())
+      return *ItImage;
+   return NULL;
+}
+
+/**
+ * \brief   Get the next entry while visiting the DicomDirImages
+ * \note : meaningfull only if GetFirstEntry already called
+ * \return  The next DicomDirImages if found, otherwhise NULL
+ */
+DicomDirImage *DicomDirSerie::GetNextImage()
+{
+   gdcmAssertMacro (ItImage != Images.end());
+
+   ++ItImage;
+   if (ItImage != Images.end())      
+      return *ItImage;
+   return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Prints the Object
+ * @param os ostream to write to
+ * @param indent Indentation string to be prepended during printing
+ */ 
+void DicomDirSerie::Print(std::ostream &os, std::string const &)
+{
+   os << "SERIE" << std::endl;
+   DicomDirObject::Print(os);
+
+   for(ListDicomDirImage::iterator cc = Images.begin();
+                                   cc != Images.end();
+                                   ++cc)
+   {
+      (*cc)->SetPrintLevel(PrintLevel);
+      (*cc)->Print(os);
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirSerie.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirSerie.h
new file mode 100644
index 0000000000000000000000000000000000000000..00b2a75228325f625bc48d72c929d42d30d4b5f1
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirSerie.h
@@ -0,0 +1,152 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirSerie.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICOMDIRSERIE_H
+#define GDCMDICOMDIRSERIE_H
+
+#include "gdcmDicomDirObject.h"
+
+namespace gdcm 
+{
+class DicomDirImage;
+//-----------------------------------------------------------------------------
+typedef std::list<DicomDirImage *> ListDicomDirImage;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief   describes a SERIE  within a within a STUDY
+ * (DicomDirStudy) of a given DICOMDIR (DicomDir)
+ */
+class GDCM_EXPORT DicomDirSerie : public DicomDirObject 
+{
+public:
+   DicomDirSerie(bool empty=false); 
+   ~DicomDirSerie();
+
+   void Print( std::ostream &os = std::cout, std::string const &indent = "" );
+   void WriteContent( std::ofstream *fp, FileType t );
+
+   // Image methods
+   DicomDirImage *NewImage();
+   /// Add a new gdcm::DicomDirImage to the Serie
+   void AddImage(DicomDirImage *obj) { Images.push_back(obj); }
+   void ClearImage();
+
+   DicomDirImage *GetFirstImage();
+   DicomDirImage *GetNextImage();
+
+private:
+
+   ///chained list of DicomDirImages (to be exploited recursively)
+   ListDicomDirImage Images;
+   /// iterator on the DicomDirImages of the current DicomDirSerie
+   ListDicomDirImage::iterator ItImage;
+
+/*
+// for future use :
+
+   /// chained list of DicomDirOverlays(single level)
+   ListDicomDirOverlay Overlays;
+   /// iterator on the DicomDirOverlays of the current DicomDirSerie
+   ListDicomDirOverlay::iterator ItOverlay;
+
+   /// chained list of DicomDirModalityLuts(single level)
+   ListDicomDirModalityLut ModalityLuts;
+   /// iterator on the DicomDirModalityLuts of the current DicomDirSerie
+   ListDicomDirModalityLut::iterator ItModalityLut;
+
+   /// chained list of DicomDirModalityLuts(single level)
+   ListDicomDirModalityLut ModalityLuts;
+   /// iterator on the DicomDirModalityLuts of the current DicomDirSerie
+   ListDicomDirModalityLut::iterator ItModalityLuts;
+
+   /// chained list of DicomDirCurves(single level)
+   ListDicomDirCurve Curves;
+   /// iterator on the DicomDirCurves of the current DicomDirSerie
+   ListDicomDirCurve::iterator ItCurves;
+
+   /// chained list of DicomDirStoredPrints(single level)
+   ListDicomDirStoredPrint StoredPrints;
+   /// iterator on the DicomDirStoredPrints of the current DicomDirSerie
+   ListDicomDirStoredPrint::iterator ItStoredPrints;
+
+   /// chained list of DicomDirRtDoses(single level)
+   ListDicomDirRtDose RtDoses;
+   /// iterator on the DicomDirRtDoses of the current DicomDirSerie
+   ListDicomDirRtDose::iterator ItRtDoses;
+
+   /// chained list of DicomDirRtStructureSets(single level)
+   ListDicomDirRtStructureSet RtStructureSets;
+   /// iterator on the DicomDirRtStructureSets of the current DicomDirSerie
+   ListDicomDirRtStructureSet::iterator ItRtStructureSets;
+
+   /// chained list of DicomDirRtPlans(single level)
+   ListDicomDirRtPlan RtPlans;
+   /// iterator on the DicomDirRtPlans of the current DicomDirSerie
+   ListDicomDirPlan::iterator ItRtPlans;
+
+   /// chained list of DicomDirRtTreatRecords(single level)
+   ListDicomDirRtTreatRecord RtTreatRecords;
+   /// iterator on the DicomDirRtTreatRecords of the current DicomDirSerie
+   ListDicomDirRtTreatRecord::iterator ItRtTreatRecords;
+
+   /// chained list of DicomDirPresentations(single level)
+   ListDicomDirPresentation Presentations;
+   /// iterator on the DicomDirPresentations of the current DicomDirSerie
+   ListDicomDirPresentation::iterator ItPresentations;
+
+   /// chained list of DicomDirWaveForms(single level)
+   ListDicomDirWaveForm WaveForms;
+   /// iterator on the DicomDirWaveForms of the current DicomDirSerie
+   ListDicomDirWaveForm::iterator ItWaveForms;
+
+   /// chained list of DicomDirSrDocuments(single level)
+   ListDicomDirSrDocument SrDocuments;
+   /// iterator on the DicomDirSrDocuments of the current DicomDirSerie
+   ListDicomDirSrDocument::iterator ItSrDocuments;
+
+   /// chained list of DicomDirKeyObjectDocs(single level)
+   ListDicomDirKeyObjectDoc KeyObjectDocs;
+   /// iterator on the DicomDirKeyObjectDocs of the current DicomDirSerie
+   ListDicomDirKeyObjectDoc::iterator ItKeyObjectDocs;
+
+   /// chained list of DicomDirSpectroscopys(single level)
+   ListDicomDirSpectroscopy Spectroscopys;
+   /// iterator on the DicomDirSpectroscopys of the current DicomDirSerie
+   ListDicomDirSpectroscopy::iterator ItSpectroscopys;
+
+   /// chained list of DicomDirRawDatas(single level)
+   ListDicomDirRawData RawDatas;
+   /// iterator on the DicomDirRawDatas of the current DicomDirSerie
+   ListDicomDirRawData::iterator ItRawDatas;
+
+   /// chained list of DicomDirRegistrations(single level)
+   ListDicomDirRegistration Registrations;
+   /// iterator on the DicomDirRegistrations of the current DicomDirSerie
+   ListDicomDirRegistration::iterator ItRegistrations;
+
+   /// chained list of DicomDirFiducials(single level)
+   ListDicomDirFiducial Fiducials;
+   /// iterator on the DicomDirFiducials of the current DicomDirSerie
+   ListDicomDirFiducial::iterator ItFiducials;
+*/
+
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirStudy.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirStudy.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..88ec946f261a0aa4ae8a60c44f69e3024e018675
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirStudy.cxx
@@ -0,0 +1,253 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirStudy.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDicomDirStudy.h"
+#include "gdcmDicomDirElement.h"
+#include "gdcmGlobal.h"
+#include "gdcmDicomDirSerie.h"
+#include "gdcmDicomDirVisit.h"
+#include "gdcmDebug.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief  Constructor 
+ * \note End user must use : DicomDirPatient::NewStudy()
+ */
+DicomDirStudy::DicomDirStudy(bool empty)
+              :DicomDirObject()
+{
+   if ( !empty )
+   {
+      ListDicomDirStudyElem const &elemList = 
+         Global::GetDicomDirElements()->GetDicomDirStudyElements();
+      FillObject(elemList);
+   }
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+DicomDirStudy::~DicomDirStudy() 
+{
+   ClearSerie();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Writes the Object
+ * @param fp ofstream to write to
+ * @param t Type of the File (explicit VR, implicitVR, ...) 
+ * @return
+ */ 
+void DicomDirStudy::WriteContent(std::ofstream *fp, FileType t)
+{
+   DicomDirObject::WriteContent(fp, t);
+
+   for(ListDicomDirSerie::iterator cc = Series.begin();
+                                   cc!= Series.end();
+                                 ++cc )
+   {
+      (*cc)->WriteContent( fp, t );
+   }
+
+   for(ListDicomDirVisit::iterator icc = Visits.begin();
+                                   icc!= Visits.end();
+                                 ++icc )
+   {
+      (*icc)->WriteContent( fp, t );
+   }
+}
+
+/**
+ * \brief   adds a new Serie at the beginning of the SerieList
+ *          of a partially created DICOMDIR
+ */
+DicomDirSerie *DicomDirStudy::NewSerie()
+{
+   DicomDirSerie *st = new DicomDirSerie();
+   Series.push_back(st);
+   return st;
+} 
+
+/**
+ * \brief  Remove all series in the study 
+ */
+void DicomDirStudy::ClearSerie()
+{
+   for(ListDicomDirSerie::iterator cc = Series.begin();
+                                   cc != Series.end();
+                                 ++cc )
+   {
+      delete *cc;
+   }
+   Series.clear();
+}
+
+/**
+ * \brief   Get the first entry while visiting the DicomDirSeries
+ * \return  The first DicomDirSerie if found, otherwhise NULL
+ */
+DicomDirSerie *DicomDirStudy::GetFirstSerie()
+{
+   ItSerie = Series.begin();
+   if (ItSerie != Series.end())
+      return *ItSerie;
+   return NULL;
+}
+
+/**
+ * \brief   Get the next entry while visiting the DicomDirSeries
+ * \note : meaningfull only if GetFirstEntry already called
+ * \return  The next DicomDirSerie if found, otherwhise NULL
+ */
+DicomDirSerie *DicomDirStudy::GetNextSerie()
+{
+   gdcmAssertMacro (ItSerie != Series.end());
+
+   ++ItSerie;
+   if (ItSerie != Series.end())
+      return *ItSerie;
+   return NULL;
+}  
+
+/**
+ * \brief   Get the last entry while visiting the DicomDirSeries
+ * \return  The last DicomDirSerie if found, otherwhise NULL
+ */
+DicomDirSerie *DicomDirStudy::GetLastSerie()
+{
+   ItSerie = Series.end();
+   if (ItSerie != Series.begin())
+   {
+     --ItSerie;
+      return *ItSerie;
+   }
+   return NULL;
+}
+
+
+/**
+ * \brief   adds a new Visit at the beginning of the VisitList
+ *          of a partially created DICOMDIR
+ */
+DicomDirVisit *DicomDirStudy::NewVisit()
+{
+   DicomDirVisit *st = new DicomDirVisit();
+   Visits.push_back(st);
+   return st;
+} 
+
+/**
+ * \brief  Remove all visits in the study 
+ */
+void DicomDirStudy::ClearVisit()
+{
+   for(ListDicomDirVisit::iterator cc =  Visits.begin();
+                                   cc != Visits.end();
+                                 ++cc )
+   {
+      delete *cc;
+   }
+   Visits.clear();
+}
+
+/**
+ * \brief   Get the first entry while visiting the DicomDirVisit
+ * \return  The first DicomDirVisit if found, otherwhise NULL
+ */
+DicomDirVisit *DicomDirStudy::GetFirstVisit()
+{
+   ItVisit = Visits.begin();
+   if (ItVisit != Visits.end())
+      return *ItVisit;
+   return NULL;
+}
+
+/**
+ * \brief   Get the next entry while visiting the DicomDirVisit
+ * \note : meaningfull only if GetFirstEntry already called
+ * \return  The next DicomDirVisit if found, otherwhise NULL
+ */
+DicomDirVisit *DicomDirStudy::GetNextVisit()
+{
+   gdcmAssertMacro (ItVisit != Visits.end());
+
+   ++ItVisit;
+   if (ItVisit != Visits.end())
+      return *ItVisit;
+   return NULL;
+}
+
+/**
+ * \brief   Get the last entry while visiting the DicomDirVisit
+ * \return  The last DicomDirVisit if found, otherwhise NULL
+ */
+DicomDirVisit *DicomDirStudy::GetLastVisit()
+{
+   ItVisit = Visits.end();
+   if (ItVisit != Visits.begin())
+   {
+     --ItVisit;
+      return *ItVisit;
+   }
+   return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Prints the Object
+ * @param os ostream to write to 
+ * @param indent Indentation string to be prepended during printing
+ * @return
+ */ 
+void DicomDirStudy::Print(std::ostream &os, std::string const & )
+{
+   os << "STUDY" << std::endl;
+   DicomDirObject::Print(os);
+
+   for(ListDicomDirSerie::iterator cc = Series.begin();
+                                   cc != Series.end();
+                                   ++cc)
+   {
+      (*cc)->SetPrintLevel(PrintLevel);
+      (*cc)->Print(os);
+   }
+
+   for(ListDicomDirVisit::iterator cc2 =  Visits.begin();
+                                   cc2 != Visits.end();
+                                   ++cc2)
+   {
+      (*cc2)->SetPrintLevel(PrintLevel);
+      (*cc2)->Print(os);
+   }
+
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirStudy.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirStudy.h
new file mode 100644
index 0000000000000000000000000000000000000000..3c4a175adb9060f72ff5dccf311efb9c91030b0d
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirStudy.h
@@ -0,0 +1,109 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirStudy.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICOMDIRSTUDY_H
+#define GDCMDICOMDIRSTUDY_H
+
+#include "gdcmDicomDirObject.h"
+
+namespace gdcm 
+{
+class DicomDirSerie;
+class DicomDirVisit;
+//-----------------------------------------------------------------------------
+typedef std::list<DicomDirSerie *> ListDicomDirSerie;
+
+
+// For future use (Full DICOMDIR)
+typedef std::list<DicomDirVisit *> ListDicomDirVisit;
+/*
+typedef std::list<DicomDirResult *> ListDicomDirResult;
+typedef std::list<DicomDirStudyComponent *> ListDicomDirStudyComponent;
+*/
+//-----------------------------------------------------------------------------
+/**
+ * \brief   describes a STUDY within a within a PATIENT
+ * (DicomDirPatient) of a given DICOMDIR (DicomDir)
+ */
+class GDCM_EXPORT DicomDirStudy : public DicomDirObject
+{
+public:
+   DicomDirStudy(bool empty=false); 
+   ~DicomDirStudy();
+
+   void Print(std::ostream &os = std::cout, std::string const &indent = "" );
+   void WriteContent(std::ofstream *fp, FileType t);
+
+   // 'Serie' methods
+   DicomDirSerie *NewSerie();
+   /// Adds a gdcm::DicomDirSerie to a gdcm::DicomDirStudy
+   void AddSerie(DicomDirSerie *obj) { Series.push_back(obj); }
+   void ClearSerie();
+   DicomDirSerie *GetFirstSerie();
+   DicomDirSerie *GetNextSerie();
+   DicomDirSerie *GetLastSerie();
+
+   // 'Visit' methods
+   DicomDirVisit *NewVisit();
+   /// Adds a gdcm::DicomDirVisit to a gdcm::DicomDirStudy
+   void AddVisit(DicomDirVisit *obj) { Visits.push_back(obj); }
+   void ClearVisit();
+   DicomDirVisit *GetFirstVisit();
+   DicomDirVisit *GetNextVisit();
+   DicomDirVisit *GetLastVisit();
+   
+   // for future use (Full DICOMDIR)
+/*
+   DicomDirResult *GetFirstResult();
+   DicomDirResult *GetNextResult();
+   DicomDirResult *GetLastResult();
+
+   DicomDirStudyComponent *GetFirstStudyComponent();
+   DicomDirStudyComponent *GetNextStudyComponent();
+   DicomDirStudyComponent *GetLastStudyComponent();
+*/    
+private:
+
+   /// chained list of DicomDirSeries (to be exploited hierarchicaly)
+   ListDicomDirSerie Series;
+   /// iterator on the DicomDirSeries of the current DicomDirStudy
+   ListDicomDirSerie::iterator ItSerie;
+
+   /// chained list of DicomDirVisits(single level)
+   ListDicomDirVisit Visits;
+   /// iterator on the DicomDirVisits of the current DicomDirStudy
+   ListDicomDirVisit::iterator ItVisit;
+   
+
+   // for future use (Full DICOMDIR)
+/*
+   /// chained list of DicomDirResults(single level)
+   ListDicomDirResult Results;
+   /// iterator on the DicomDirResults of the current DicomDirStudy
+   ListDicomDirResult::iterator ItResult;
+
+   /// chained list of DicomDirStudyComponents(single level)
+   ListDicomDirStudyComponent StudyComponents;
+   /// iterator on the DicomDirStudyComponents of the current DicomDirStudy
+   ListDicomDirStudyComponent::iterator ItStudyComponents;
+*/
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirVisit.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirVisit.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..60f288070c41df4c8edc943010536af147f229f4
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirVisit.cxx
@@ -0,0 +1,86 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirVisit.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.2 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDicomDirVisit.h"
+#include "gdcmValEntry.h"
+#include "gdcmGlobal.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief  Constructor 
+ * \note End user must use : DicomDirStudy::NewVisit()
+ */
+DicomDirVisit::DicomDirVisit(bool empty):
+   DicomDirObject()
+{
+   if ( !empty )
+   {
+      ListDicomDirVisitElem const &elemList = 
+         Global::GetDicomDirElements()->GetDicomDirVisitElements();
+      FillObject(elemList);
+   }
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+DicomDirVisit::~DicomDirVisit() 
+{
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Prints the Object
+ * @param os ostream to write to
+ * @param indent Indentation string to be prepended during printing
+ * @return
+ */ 
+void DicomDirVisit::Print(std::ostream &os, std::string const & )
+{
+   os << "VISIT : ";
+   for(ListDocEntry::iterator i = DocEntries.begin();
+                              i!= DocEntries.end();
+                              ++i)
+   {
+      if ( (*i)->GetGroup() == 0x0004 && (*i)->GetElement() == 0x1500 )
+      {
+         if( dynamic_cast<ValEntry *>(*i) )
+            os << (dynamic_cast<ValEntry *>(*i))->GetValue();
+      }
+   }
+   os << std::endl;
+
+   DicomDirObject::Print(os);
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirVisit.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirVisit.h
new file mode 100644
index 0000000000000000000000000000000000000000..fdb34ecd8e8732669d648e1869726f82fda52ddc
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDicomDirVisit.h
@@ -0,0 +1,43 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDicomDirVisit.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.2 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICOMDIRVISIT_H
+#define GDCMDICOMDIRVISIT_H
+
+#include "gdcmDicomDirObject.h"
+
+namespace gdcm 
+{
+
+/**
+ * \brief   describes a VISIT  within a within a STUDY
+ * (DicomDirStudy) of a given DICOMDIR (DicomDir)
+ */
+class GDCM_EXPORT DicomDirVisit : public DicomDirObject 
+{
+public:
+   DicomDirVisit(bool empty=false); 
+   ~DicomDirVisit();
+
+   void Print( std::ostream &os = std::cout, std::string const &indent = "" );
+  // void WriteContent( std::ofstream *fp, FileType t );
+
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDict.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDict.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..16a2017662b8d92e886f413394e36989331a5f62
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDict.cxx
@@ -0,0 +1,334 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDict.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.8 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDict.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/// \brief auto generated function, to fill up the Dicom Dictionnary,
+///       if relevant file is not found on user's disk
+void FillDefaultDataDict(Dict *d);
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor
+ */
+Dict::Dict( )
+{
+   Filename="";
+}
+
+/**
+ * \brief   Constructor
+ * @param   filename from which to build the dictionary.
+ */
+Dict::Dict(std::string const &filename)
+{
+
+   std::ifstream from( filename.c_str() );
+   if ( !from )
+   {
+      gdcmWarningMacro( "Can't open dictionary" << filename.c_str());
+      // Using default embeded one:
+      FillDefaultDataDict( this );
+   }
+   else
+   {
+      DoTheLoadingJob(from);
+      Filename = filename;
+   }
+}
+
+/**
+ * \brief  Destructor 
+ */
+Dict::~Dict()
+{
+   ClearEntry();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+/**
+ * \brief   Add a all the entries held in a source dictionary
+ * \note it concerns only Private Dictionnary
+ * @param   filename from which to build the dictionary.
+ */
+bool Dict::AddDict(std::string const &filename)
+{
+
+   std::ifstream from( filename.c_str() );
+   if ( !from )
+   {
+      gdcmWarningMacro( "Can't open dictionary" << filename.c_str());
+      return false;
+   }
+   else
+   {
+      DoTheLoadingJob(from);
+      return true;
+   }
+}
+
+
+/**
+ * \brief   Removes from the current Dicom Dict all the entries held in a source dictionary
+ * \note it concerns only Private Dictionnary
+ * @param   filename from which we read the entries to remove.
+ */
+bool Dict::RemoveDict(std::string const &filename)
+{
+   std::ifstream from( filename.c_str() );
+   if ( !from )
+   {
+      gdcmWarningMacro( "Can't open dictionary" << filename.c_str());
+      return false;
+   }
+   else
+   {
+      uint16_t group;
+      uint16_t elem;
+      TagName vr;
+      TagName vm;
+      TagName name;
+
+      while (!from.eof() && from)
+      {
+         from >> std::hex;
+         from >> group;
+         from >> elem;
+         from >> vr;
+         from >> vm;
+        // from >> std::ws;  //remove white space
+         std::getline(from, name);
+ 
+         RemoveEntry(DictEntry::TranslateToKey(group, elem));
+      }
+      from.close();
+      return true;
+   }
+}
+
+/**
+ * \brief  adds a new Dicom Dictionary Entry 
+ * @param   newEntry entry to add 
+ * @return  false if Dicom Element already exists
+ */
+bool Dict::AddEntry(DictEntry const &newEntry) 
+{
+   const TagKey &key = newEntry.GetKey();
+
+   if ( KeyHt.count(key) == 1 )
+   {
+      gdcmErrorMacro( "Already present:" << key );
+      return false;
+   } 
+   else 
+   {
+      KeyHt.insert( TagKeyHT::value_type(newEntry.GetKey(), newEntry));
+      return true;
+   }
+}
+
+/**
+ * \brief  replaces an already existing Dicom Element by a new one
+ * @param   newEntry new entry (overwrites any previous one with same tag)
+ * @return  false if Dicom Element doesn't exist
+ */
+bool Dict::ReplaceEntry(DictEntry const &newEntry)
+{
+   if ( RemoveEntry(newEntry.GetKey()) )
+   {
+       KeyHt.insert( TagKeyHT::value_type(newEntry.GetKey(), newEntry));
+       return true;
+   } 
+   return false;
+}
+
+/**
+ * \brief  removes an already existing Dicom Dictionary Entry,
+ *         identified by its Tag
+ * @param   key (group|element)
+ * @return  false if Dicom Dictionary Entry doesn't exist
+ */
+bool Dict::RemoveEntry(TagKey const &key) 
+{
+   TagKeyHT::const_iterator it = KeyHt.find(key);
+   if ( it != KeyHt.end() ) 
+   {
+      KeyHt.erase(key);
+
+      return true;
+   } 
+   else 
+   {
+      gdcmWarningMacro( "Unfound entry" << key );
+      return false;
+  }
+}
+
+/**
+ * \brief  removes an already existing Dicom Dictionary Entry, 
+ *          identified by its group,element number
+ * @param   group   Dicom group number of the Dicom Element
+ * @param   elem Dicom element number of the Dicom Element
+ * @return  false if Dicom Dictionary Entry doesn't exist
+ */
+bool Dict::RemoveEntry(uint16_t group, uint16_t elem)
+{
+   return RemoveEntry(DictEntry::TranslateToKey(group, elem));
+}
+
+/**
+ * \brief   Remove all Dicom Dictionary Entries
+ */
+void Dict::ClearEntry()
+{
+   // we assume all the pointed DictEntries are already cleaned-up
+   // when we clean KeyHt.
+   KeyHt.clear();
+}
+
+/**
+ * \brief   Get the dictionary entry identified by a given tag ("group|element")
+ * @param   key   tag of the searched entry 
+ * @return  the corresponding dictionary entry when existing, NULL otherwise
+ */
+DictEntry *Dict::GetEntry(TagKey const &key)
+{
+   TagKeyHT::iterator it = KeyHt.find(key);
+   if ( it == KeyHt.end() )
+   {
+      return 0;
+   }
+   return &(it->second);
+}
+
+/**
+ * \brief   Get the dictionary entry identified by it's "group" and "element")
+ * @param   group  Group number of the searched entry.
+ * @param   elem Element number of the searched entry.
+ * @return  the corresponding dictionary entry when existing, NULL otherwise
+ */
+DictEntry *Dict::GetEntry(uint16_t group, uint16_t elem)
+{
+   TagKey key = DictEntry::TranslateToKey(group, elem);
+   TagKeyHT::iterator it = KeyHt.find(key);
+   if ( it == KeyHt.end() )
+   {
+      return 0;
+   }
+   return &(it->second);
+}
+
+/**
+ * \brief   Get the first entry while visiting the Dict entries
+ * \return  The first DicEntry if found, otherwhise NULL
+ */
+DictEntry *Dict::GetFirstEntry()
+{
+   ItKeyHt = KeyHt.begin();
+   if ( ItKeyHt != KeyHt.end() )
+      return &(ItKeyHt->second);
+   return NULL;
+}
+
+/**
+ * \brief   Get the next entry while visiting the Hash table (KeyHt)
+ * \note : meaningfull only if GetFirstEntry already called
+ * \return  The next DictEntry if found, otherwhise NULL
+ */
+DictEntry *Dict::GetNextEntry()
+{
+   gdcmAssertMacro (ItKeyHt != KeyHt.end());
+
+   ++ItKeyHt;
+   if (ItKeyHt != KeyHt.end())
+      return &(ItKeyHt->second);
+   return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \brief Add all the dictionary entries from an already open source file 
+ * @param from input stream to read from.
+ */
+void Dict::DoTheLoadingJob(std::ifstream &from)
+{
+   uint16_t group;
+   uint16_t elem;
+   TagName vr;
+   TagName vm;
+   TagName name;
+
+   while (!from.eof() && from)
+   {
+      from >> std::hex;
+      from >> group;
+      from >> elem;
+      from >> vr;
+      from >> vm;
+      from >> std::ws;  //remove white space
+      std::getline(from, name);
+
+      const DictEntry newEntry(group, elem, vr, vm, name);
+      AddEntry(newEntry);
+   }
+   from.close();
+}
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Print all the dictionary entries contained in this dictionary.
+ *          Entries will be sorted by tag i.e. the couple (group, element).
+ * @param   os The output stream to be written to.
+ * @param indent Indentation string to be prepended during printing
+ */
+void Dict::Print(std::ostream &os, std::string const & )
+{
+   os << "Dict file name : " << Filename << std::endl;
+   itksys_ios::ostringstream s;
+
+   for (TagKeyHT::iterator tag = KeyHt.begin(); tag != KeyHt.end(); ++tag)
+   {
+      s << "Entry : ";
+      s << "(" << std::hex << std::setw(4) << tag->second.GetGroup() << ',';
+      s << std::hex << std::setw(4) << tag->second.GetElement() << ") = "
+        << std::dec;
+      s << tag->second.GetVR() << ", ";
+      s << tag->second.GetVM() << ", ";
+      s << tag->second.GetName() << "."  << std::endl;
+   }
+   os << s.str();
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDict.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDict.h
new file mode 100644
index 0000000000000000000000000000000000000000..33d0935f5041bcc0aa3659348e9e6136cd6dbd01
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDict.h
@@ -0,0 +1,86 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDict.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICT_H
+#define GDCMDICT_H
+
+#include "gdcmBase.h"
+#include "gdcmDictEntry.h"
+
+#include <iostream>
+#include <fstream> // for ifstream
+#include <list>
+#include <map>
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+typedef std::string DictKey;
+typedef std::map<TagKey, DictEntry>  TagKeyHT;
+//-----------------------------------------------------------------------------
+/**
+ * \brief    Dict acts a memory representation of a dicom dictionary i.e.
+ *           it is a container for a collection of dictionary entries.
+ *           The dictionary is loaded from in an ascii file.
+ *           There should be a single public dictionary (THE dictionary of
+ *           the actual DICOM v3) but as many shadow dictionaries as imagers 
+ *           combined with all software versions...
+ * \see DictSet
+ */
+class GDCM_EXPORT Dict : public Base
+{
+public:
+   Dict();
+   Dict(std::string const &filename);
+   ~Dict();
+
+   bool AddDict(std::string const &filename);
+   bool RemoveDict(std::string const &filename);
+// Print
+   void Print(std::ostream &os = std::cout, std::string const &indent = "");
+
+// Entries
+   bool AddEntry(DictEntry const &newEntry);
+   bool ReplaceEntry(DictEntry const &newEntry);
+   bool RemoveEntry (TagKey const &key);
+   bool RemoveEntry (uint16_t group, uint16_t elem);
+   void ClearEntry();
+   
+// Tag
+   DictEntry *GetEntry(uint16_t group, uint16_t elem);
+   DictEntry *GetEntry(TagKey const &key);
+
+   DictEntry *GetFirstEntry();
+   DictEntry *GetNextEntry();
+
+private:
+   void DoTheLoadingJob(std::ifstream &ifs);
+
+   /// ASCII file holding the Dictionnary
+   std::string Filename;
+
+   /// Access through TagKey
+   TagKeyHT KeyHt;
+   /// Iterator for the entries
+   TagKeyHT::iterator ItKeyHt;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDictEntry.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDictEntry.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e4af35dbf00fc6558df7d42e0cd92e413967a890
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDictEntry.cxx
@@ -0,0 +1,152 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDictEntry.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.6 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDictEntry.h"
+#include "gdcmDebug.h"
+#include "gdcmUtil.h"
+
+#include <iomanip> // for std::ios::left, ...
+#include <fstream>
+#include <stdio.h> // for sprintf
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor
+ * @param   group      DICOM-Group Number
+ * @param   elem       DICOM-Element Number
+ * @param   vr         Value Representation
+ * @param   vm         Value Multiplicity 
+ * @param   name       description of the element
+*/
+
+DictEntry::DictEntry(uint16_t group, uint16_t elem,
+                     TagName const &vr, 
+                     TagName const &vm,
+                     TagName const &name)
+{
+   Group   = group;
+   Element = elem;
+   VR      = vr;
+   VM      = vm;
+   Name    = name;
+   Key     = TranslateToKey(group, elem);
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief       If-and only if-the V(alue) R(epresentation)
+ * \            is unset then overwrite it.
+ * @param vr    New V(alue) R(epresentation) to be set.
+ */
+void DictEntry::SetVR(TagName const &vr) 
+{
+   if ( IsVRUnknown() )
+   {
+      VR = vr;
+   }
+   else 
+   {
+      gdcmErrorMacro( "Overwriting VR might compromise a dictionary");
+   }
+}
+
+/**
+ * \brief       If-and only if-the V(alue) M(ultiplicity)
+ * \            is unset then overwrite it.
+ * @param vm    New V(alue) M(ultiplicity) to be set.
+ */
+void DictEntry::SetVM(TagName const &vm) 
+{
+   if ( IsVMUnknown() )
+   {
+      VM = vm;
+   }
+   else 
+   {
+      gdcmErrorMacro( "Overwriting VM might compromise a dictionary");
+   }
+}
+
+/**
+ * \brief   concatenates 2 uint16_t (supposed to be a Dicom group number 
+ *                                              and a Dicom element number)
+ * @param  group the Dicom group number used to build the tag
+ * @param  elem the Dicom element number used to build the tag
+ * @return the built tag
+ */
+TagKey DictEntry::TranslateToKey(uint16_t group, uint16_t elem)
+{
+   // according to 'Purify', TranslateToKey is one of the most
+   // time consuming methods.
+   // Let's try to shorten it !
+ 
+   //return Util::Format("%04x|%04x", group, elem); // too much time !
+#if FASTTAGKEY
+   TagKey r;
+   r.tab[0] = group;
+   r.tab[1] = elem;
+   return r;
+#else
+   char res[10];
+   sprintf(res,"%04x|%04x", group, elem);
+   return res;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Prints an entry of the Dicom DictionaryEntry
+ * @param   os ostream we want to print in
+ * @param indent Indentation string to be prepended during printing
+ */
+void DictEntry::Print(std::ostream &os, std::string const & )
+{
+   std::string vr;
+   itksys_ios::ostringstream s;
+
+   vr = GetVR();
+   if ( vr==GDCM_UNKNOWN )
+      vr="  ";
+
+   s << DictEntry::TranslateToKey(GetGroup(),GetElement()); 
+   s << " [" << vr  << "] ";
+
+   if ( PrintLevel >= 1 )
+   {
+      s.setf(std::ios::left);
+      s << std::setw(66-GetName().length()) << " ";
+   }
+
+   s << "[" << GetName()<< "]";
+   os << s.str() << std::endl;
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDictEntry.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDictEntry.h
new file mode 100644
index 0000000000000000000000000000000000000000..24bb9f8963f84fcc333d3c519ad19a77f5ada179
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDictEntry.h
@@ -0,0 +1,175 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDictEntry.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 17:53:28 $
+  Version:   $Revision: 1.5 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICTENTRY_H
+#define GDCMDICTENTRY_H
+
+#include "gdcmBase.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/**
+ * \brief
+ * the DictEntry in an element contained by the Dict.
+ * It contains :
+ *  - the key referenced by the DICOM norm or the constructor (for private keys)
+ *    i.e. the Group number
+ *         the Element number
+ *  - the VR (Value Representation)
+ *  - the VM (Value Multiplicity)
+ *  - the corresponding name in english
+ */
+class GDCM_EXPORT DictEntry : public Base
+{
+public:
+   DictEntry(uint16_t group, 
+             uint16_t elem,
+             TagName const &vr     = GDCM_UNKNOWN,
+             TagName const &vm     = GDCM_UNKNOWN,
+             TagName const &name   = GDCM_UNKNOWN);
+
+// Print
+   void Print(std::ostream &os = std::cout, std::string const &indent = "");
+
+// Content of DictEntry
+   void SetVR(TagName const &vr);
+   void SetVM(TagName const &vm);
+
+   /// \brief tells if the V(alue) R(epresentation) is known (?!)
+   /// @return 
+   bool IsVRUnknown() { return VR == GDCM_UNKNOWN; }
+
+   /// \brief tells if the V(alue) M(ultiplicity) is known (?!)
+   /// @return 
+   bool IsVMUnknown() { return VM == GDCM_UNKNOWN; }
+
+   /// \brief  Returns the Dicom Group Number of the current DictEntry
+   /// @return the Dicom Group Number
+   uint16_t GetGroup() const { return Group; }
+  
+   /// \brief  Returns the Dicom Element Number of the current DictEntry
+   /// @return the Dicom Element Number
+   uint16_t GetElement() const { return Element; }
+ 
+   /// \brief  Returns the Dicom Value Representation of the current
+   ///         DictEntry
+   /// @return the Dicom Value Representation
+   const TagName &GetVR() const { return VR; }
+ 
+   /// \brief   sets the key of the current DictEntry
+   /// @param k New key to be set.
+   void SetKey(TagKey const &k)  { Key = k; }
+ 
+   /// \brief   returns the VM field of the current DictEntry
+   /// @return  The 'Value Multiplicity' field
+   const TagName &GetVM() const { return VM; } 
+
+   /// \brief  Returns the Dicom Name of the current DictEntry
+   ///         e.g. "Patient Name" for Dicom Tag (0x0010, 0x0010) 
+   /// @return the Dicom Name
+   const TagName &GetName() const { return Name; } 
+ 
+   /// \brief  Gets the key of the current DictEntry
+   /// @return the key.
+   const TagKey &GetKey() const { return Key; }
+
+// Key creation
+   static TagKey TranslateToKey(uint16_t group, uint16_t elem);
+
+private:
+   /// \todo FIXME 
+   ///        where are the group and elem used except from building up
+   ///        a TagKey. If the answer is nowhere then there is no need
+   ///        to store the group and elem independently.
+   ///
+   ///        --> EVERYWHERE ! The alternate question would be :
+   ///                         What's TagKey used for ?
+   
+   /// DicomGroup number
+   uint16_t Group;   // e.g. 0x0010
+
+   /// DicomElement number
+   uint16_t Element; // e.g. 0x0103
+
+   /// \brief Value Representation i.e. some clue about the nature
+   ///        of the data represented e.g. 
+   ///        "FD" short for "Floating Point Double"(see \ref VR)
+   ///        "PN" short for "Person Name"       
+   TagName VR;
+
+   /*
+    *  .
+    *  Formerly 'Group name abbreviations'
+    *  Here is a small dictionary we encountered in "nature":
+    *  - CMD      Command        
+    *  - META     Meta Information 
+    *  - DIR      Directory
+    *  - ID       ???
+    *  - PAT      Patient
+    *  - ACQ      Acquisition
+    *  - REL      Related
+    *  - IMG      Image
+    *  - SDY      Study
+    *  - VIS      Visit 
+    *  - WAV      Waveform
+    *  - PRC      ???
+    *  - DEV      Device
+    *  - NMI      Nuclear Medicine
+    *  - MED      ???
+    *  - BFS      Basic Film Session
+    *  - BFB      Basic Film Box
+    *  - BIB      Basic Image Box
+    *  - BAB
+    *  - IOB
+    *  - PJ
+    *  - PRINTER
+    *  - RT       Radio Therapy
+    *  - DVH   
+    *  - SSET
+    *  - RES      Results
+    *  - CRV      Curve
+    *  - OLY      Overlays
+    *  - PXL      Pixels
+    *  - DL       Delimiters
+    *  .
+    *
+    *  Other usefull abreviations used for Radiographic view associated with
+    *  Patient Position (0018,5100):
+    *  -  AP = Anterior/Posterior 
+    *  -  PA = Posterior/Anterior 
+    *  -  LL = Left Lateral 
+    *  -  RL = Right Lateral 
+    *  - RLD = Right Lateral Decubitus 
+    *  - LLD = Left  Lateral Decubitus 
+    *  - RLO = Right Lateral Oblique 
+    *  - LLO = Left  Lateral Oblique  
+    *  .
+    */
+   /// \brief Value Multiplicity (e.g. "1", "1-n", "6")
+   TagName VM; 
+
+   /// \brief English name of the entry (e.g. "Patient's Name")                   
+   TagName Name;      
+
+   /// Redundant with (group, elem) but we add it for efficiency purpose.
+   TagKey  Key;
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDictGroupName.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDictGroupName.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..784ce9842902365d08b019627491f5aa946ecd87
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDictGroupName.cxx
@@ -0,0 +1,119 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDictGroupName.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDictGroupName.h"
+#include "gdcmUtil.h"
+#include "gdcmDictSet.h"
+#include "gdcmDebug.h"
+
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/// \brief auto generated function, to fill up the 'Group Name'
+///        Dictionnary, if relevant file is not found on user's disk
+void FillDefaultDictGroupName(DictGroupNameHT &groupName);
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief Constructor
+ */
+DictGroupName::DictGroupName() 
+{
+   std::string filename = DictSet::BuildDictPath() + DICT_GROUP_NAME;
+   std::ifstream from(filename.c_str());
+   if ( !from )
+   {
+      gdcmWarningMacro("Can't open dictionary" << filename.c_str());
+      FillDefaultDictGroupName(groupName);
+   }
+   else
+   {
+      char buff[1024];
+      uint16_t key;
+      TagName value;
+   
+      while (!from.eof()) 
+      {
+         from >> std::ws;
+         from >> std::hex;
+         from >> key;
+         from >> std::ws;
+         from.getline(buff, 1024, '"');
+         from.getline(buff, 1024, '"');
+         value = buff;
+         if ( !from.eof() )
+            groupName[key] = value;
+
+         from.getline(buff, 1024, '\n');
+      }
+      from.close();
+   }
+}
+
+/**
+ * \brief Destructor
+ */
+DictGroupName::~DictGroupName()
+{
+   groupName.clear();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/// \returns the formerly NIH defined ACR-NEMA group name
+const TagName &DictGroupName::GetName(uint16_t group)
+{
+   DictGroupNameHT::const_iterator it = groupName.find(group);
+   if ( it == groupName.end() )
+   {
+      return GDCM_UNFOUND;
+   }
+   return it->second;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Print all 
+ * @param   os The output stream to be written to.
+ */
+void DictGroupName::Print(std::ostream &os,std::string const &) 
+{
+   itksys_ios::ostringstream s;
+
+   for (DictGroupNameHT::iterator it = groupName.begin(); it != groupName.end(); ++it)
+   {
+      s << "DictGroupName : 0x" << std::hex << std::setw(4) << it->first 
+        << std::dec << " = " << it->second << std::endl;
+   }
+   os << s.str();
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDictGroupName.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDictGroupName.h
new file mode 100644
index 0000000000000000000000000000000000000000..00a82f63ca8ac8055dcd3ac1f071c1236bb4d35f
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDictGroupName.h
@@ -0,0 +1,57 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDictGroupName.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.2 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICTGROUPNAME_H
+#define GDCMDICTGROUPNAME_H
+
+#include "gdcmCommon.h"
+#include <map>
+#include <string>
+#include <iostream>
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+/// Group Name Hash Table
+typedef std::map<uint16_t, TagName> DictGroupNameHT;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief Container for dicom 'Group Name' Hash Table.
+ *        (formerly NIH defined ACR-NEMA group name)
+ * \note   This is a singleton
+ */
+class GDCM_EXPORT DictGroupName 
+{
+public:
+   DictGroupName(void);
+   ~DictGroupName();
+
+   void Print(std::ostream &os = std::cout, 
+              std::string const &indent = "" );
+
+   const TagName &GetName(uint16_t group);
+
+private:
+   DictGroupNameHT groupName;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDictSet.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDictSet.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..aff47d49c31a3acc2298302db6a30112b99b2fa6
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDictSet.cxx
@@ -0,0 +1,240 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDictSet.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.6 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDictSet.h"
+#include "gdcmDebug.h"
+#include <fstream>
+#include <stdlib.h>  // For getenv
+#include <stdio.h>   // For sprintf
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/** 
+ * \brief   The Dictionary Set obtained with this constructor simply
+ *          contains the Default Public dictionary.
+ */
+DictSet::DictSet() 
+{
+   DictPath = BuildDictPath();
+   std::string pubDictFile(DictPath);
+   pubDictFile += PUB_DICT_FILENAME;
+   Dicts[PUB_DICT_NAME] = new Dict(pubDictFile);
+}
+
+/**
+ * \brief  Destructor 
+ */
+DictSet::~DictSet() 
+{
+   // Remove dictionaries
+   for (DictSetHT::iterator tag = Dicts.begin(); tag != Dicts.end(); ++tag) 
+   {
+      Dict *entryToDelete = tag->second;
+      if ( entryToDelete )
+      {
+         delete entryToDelete;
+      }
+      tag->second = NULL;
+   }
+   Dicts.clear();
+
+   // Remove virtual dictionary entries
+   VirtualEntries.clear();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Loads a dictionary from a specified file, and add it
+ *          to already the existing ones contained in this DictSet.
+ * @param   filename Absolute or relative filename containing the
+ *          dictionary to load.
+ * @param   name Symbolic name that be used as identifier of the newly 
+ *          created dictionary.
+ */
+Dict *DictSet::LoadDictFromFile(std::string const &filename, 
+                                DictKey const &name) 
+{
+   Dict *newDict = new Dict(filename);
+   AppendDict(newDict, name);
+
+   return newDict;
+}
+
+/**
+ * \brief   Retrieve the specified dictionary (when existing) from this
+ *          DictSet.
+ * @param   dictName The symbolic name of the searched dictionary.
+ * \result  The retrieved dictionary.
+ */
+Dict *DictSet::GetDict(DictKey const &dictName) 
+{
+   DictSetHT::iterator dict = Dicts.find(dictName);
+   if ( dict != Dicts.end() )
+   {
+      return dict->second;
+   }
+   return NULL;
+}
+
+/**
+ * \brief   Create a DictEntry which will be referenced in no dictionary
+ * @param   group   Group number of the Entry 
+ * @param   elem  Element number of the Entry
+ * @param   vr  Value Representation of the Entry
+ * @param   vm  Value Multiplicity of the Entry
+ * @param   name  English name of the Entry
+ * @return  virtual entry
+ */
+DictEntry *DictSet::NewVirtualDictEntry( uint16_t group,
+                                         uint16_t elem,
+                                         TagName vr,
+                                         TagName vm,
+                                         TagName name)
+{
+   DictEntry *entry;
+
+  // Let's follow 'Purify' advice
+  //
+  // const std::string tag = DictEntry::TranslateToKey(group,elem)
+  //                         + "#" + vr + "#" + vm + "#" + name;
+#if FASTTAGKEY && 0
+   // FIXME
+   TagKey tag;
+   tag.tab[0] = group;
+   tag.tab[1] = elem;
+#else
+   char res[10];
+   sprintf(res,"%04x|%04x", group, elem);
+   ExtendedTagKey tag = res;
+   tag += "#" + vr + "#" + vm + "#" + name;  
+#endif
+  
+   ExtendedTagKeyHT::iterator it;
+   
+   it = VirtualEntries.find(tag);
+   if ( it != VirtualEntries.end() )
+   {
+      entry = &(it->second);
+   }
+   else
+   {
+      DictEntry ent(group, elem, vr, vm, name);
+      VirtualEntries.insert(
+         ExtendedTagKeyHT::value_type(tag, ent) );
+      entry = &(VirtualEntries.find(tag)->second);
+   }
+
+   return entry;
+}
+
+/**
+ * \brief   Get the first entry while visiting the DictSet
+ * \return  The first Dict if found, otherwhise NULL
+ */
+Dict *DictSet::GetFirstEntry()
+{
+   ItDictHt = Dicts.begin();
+   if ( ItDictHt != Dicts.end() )
+      return ItDictHt->second;
+   return NULL;
+}
+
+/**
+ * \brief   Get the next entry while visiting the Hash table (DictSetHT)
+ * \note : meaningfull only if GetFirstEntry already called
+ * \return  The next Dict if found, otherwhise NULL
+ */
+Dict *DictSet::GetNextEntry()
+{
+   gdcmAssertMacro (ItDictHt != Dicts.end());
+  
+   ++ItDictHt;
+   if ( ItDictHt != Dicts.end() )
+      return ItDictHt->second;
+   return NULL;
+}
+
+/**
+ * \brief   Obtain from the GDCM_DICT_PATH environnement variable the
+ *          path to directory containing the dictionaries. When
+ *          the environnement variable is absent the path is defaulted
+ *          to "../Dicts/".
+ * @return  path to directory containing the dictionaries
+ */
+std::string DictSet::BuildDictPath() 
+{
+   std::string resultPath;
+   const char *envPath;
+   envPath = getenv("GDCM_DICT_PATH");
+
+   if (envPath && (strlen(envPath) != 0)) 
+   {
+      resultPath = envPath;
+      gdcmWarningMacro( "Dictionary path set from environnement");
+   } 
+   else
+   {
+      resultPath = PUB_DICT_PATH;
+   }
+   if ( resultPath[resultPath.length()-1] != '/' )
+   {
+      resultPath += '/';
+   }
+
+   return resultPath;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+/**
+ * \brief   Adds a Dictionary to a DictSet
+ * \return  always true
+ */
+bool DictSet::AppendDict(Dict *newDict, DictKey const &name)
+{
+   Dicts[name] = newDict;
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Print, in an informal fashion, the list of all the dictionaries
+ *          contained is this DictSet, along with their respective content.
+ * @param   os Output stream used for printing.
+ * @param indent Indentation string to be prepended during printing
+ */
+void DictSet::Print(std::ostream &os, std::string const & )
+{
+   for (DictSetHT::iterator dict = Dicts.begin(); dict != Dicts.end(); ++dict)
+   {
+      os << "Printing dictionary " << dict->first << std::endl;
+      dict->second->Print(os);
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDictSet.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDictSet.h
new file mode 100644
index 0000000000000000000000000000000000000000..fcaadf5c20e40285fcda1391c0e9368dbcba94dd
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDictSet.h
@@ -0,0 +1,94 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDictSet.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDICTSET_H
+#define GDCMDICTSET_H
+
+#include "gdcmBase.h"
+#include "gdcmDict.h"
+
+#include <map>
+#include <list>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+typedef std::map<DictKey, Dict*> DictSetHT;
+typedef std::string ExtendedTagKey;
+typedef std::map<ExtendedTagKey, DictEntry>  ExtendedTagKeyHT;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief  Container for managing a set of loaded dictionaries (Dict).
+ * \note   Hopefully, sharing dictionaries should avoid
+ *         - reloading an already loaded dictionary (saving time)
+ *         - having many in memory representations of the same dictionary
+ *        (saving memory).
+ */
+class GDCM_EXPORT DictSet : public Base
+{
+public:
+   DictSet();
+   ~DictSet();
+
+   void Print(std::ostream &os = std::cout, std::string const &indent = "" );
+
+   // Probabely useless !
+   //EntryNamesList *GetPubDictEntryNames();
+   //EntryNamesByCatMap *GetPubDictEntryNamesByCategory();
+
+   Dict *LoadDictFromFile( std::string const &fileName,
+                           DictKey const &name );
+
+   Dict *GetDict( DictKey const &DictName );
+
+   /// \brief   Returns the default reference DICOM V3 public dictionary.
+   Dict* GetDefaultPubDict() { return GetDict(PUB_DICT_NAME); }
+
+   // \ brief   Returns the virtual references DICOM dictionary.
+   // \ warning : not end user intended
+   // Dict *GetVirtualDict() { return &VirtualEntries; }
+
+   DictEntry *NewVirtualDictEntry(uint16_t group, uint16_t elem,
+                                  TagName vr     = GDCM_UNKNOWN,
+                                  TagName vm     = GDCM_UNKNOWN,
+                                  TagName name   = GDCM_UNKNOWN);
+
+   Dict *GetFirstEntry();
+   Dict *GetNextEntry();
+
+   static std::string BuildDictPath();
+
+protected:
+   bool AppendDict(Dict *NewDict, DictKey const &name);
+
+private:
+   /// Hash table of all dictionaries contained in this DictSet
+   DictSetHT Dicts;
+   DictSetHT::iterator ItDictHt;
+
+   /// Directory path to dictionaries
+   std::string DictPath;
+
+   /// H table for the on the fly created DictEntries  
+   ExtendedTagKeyHT VirtualEntries; 
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDirList.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDirList.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5dedd89ea349cf15d8e7be37fb8472b9885d7127
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDirList.cxx
@@ -0,0 +1,208 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDirList.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.7 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDirList.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+
+#include <iterator>
+#include <assert.h>
+#include <errno.h>
+#include <sys/stat.h>  //stat function
+
+#ifdef _MSC_VER
+   #include <windows.h> 
+   #include <direct.h>
+#else
+   #include <dirent.h>   
+   #include <sys/types.h>
+#endif
+
+namespace gdcm
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief Constructor  
+ * @param  dirName root directory name
+ * @param  recursive whether we want to explore recursively or not 
+ */
+DirList::DirList(std::string const &dirName, bool recursive)
+{
+   DirName = dirName;
+   Explore(dirName, recursive);
+}
+
+/**
+ * \brief  Destructor
+ */
+DirList::~DirList()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief Tells us if file name corresponds to a Directory   
+ * @param  dirName file name to check
+ * @return true if the file IS a Directory
+ */
+bool DirList::IsDirectory(std::string const &dirName)
+{
+   struct stat fs;
+   assert( dirName[dirName.size()-1] != '/' );
+   if ( stat(dirName.c_str(), &fs) == 0 )
+   {
+#if _WIN32
+      return ((fs.st_mode & _S_IFDIR) != 0);
+#else
+      return S_ISDIR(fs.st_mode);
+#endif
+   }
+   else
+   {
+      const char *str = strerror(errno);
+      gdcmErrorMacro( str );
+      return false;
+   }
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \brief   Explore a directory with possibility of recursion
+ *          return number of files read
+ * @param  dirpath   directory to explore
+ * @param  recursive whether we want recursion or not
+ */
+int DirList::Explore(std::string const &dirpath, bool recursive)
+{
+   int numberOfFiles = 0;
+   std::string fileName;
+   std::string dirName = Util::NormalizePath(dirpath);
+#ifdef _MSC_VER
+   WIN32_FIND_DATA fileData;
+   //assert( dirName[dirName.size()-1] == '' );
+   HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
+
+   for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
+       b = FindNextFile(hFile, &fileData))
+   {
+      fileName = fileData.cFileName;
+      if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+      {
+         // Need to check for . and .. to avoid infinite loop
+         if ( fileName != "." && fileName != ".." && recursive )
+         {
+            numberOfFiles += Explore(dirName+fileName,recursive);
+         }
+      }
+      else
+      {
+         Filenames.push_back(dirName+fileName);
+         numberOfFiles++;
+      }
+   }
+   DWORD dwError = GetLastError();
+   if (hFile != INVALID_HANDLE_VALUE) 
+      FindClose(hFile);
+   if (dwError != ERROR_NO_MORE_FILES) 
+   {
+      LPVOID lpMsgBuf;
+      FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
+                    FORMAT_MESSAGE_FROM_SYSTEM|
+                    FORMAT_MESSAGE_IGNORE_INSERTS,
+                    NULL,GetLastError(),
+                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+                    (LPTSTR) &lpMsgBuf,0,NULL);
+
+      gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
+                   <<" for the directory : "<<dirName);
+      return -1;
+   }
+
+#else
+  // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
+  // work on debian for example
+
+   DIR* dir = opendir(dirName.c_str());
+   if (!dir)
+   {
+      return 0;
+   }
+
+   // According to POSIX, the dirent structure contains a field char d_name[]
+   // of unspecified size, with at most NAME_MAX characters preceeding the
+   // terminating null character. Use of other fields will harm the  porta-
+   // bility of your programs.
+
+   struct stat buf;
+   dirent *d;
+   for (d = readdir(dir); d; d = readdir(dir))
+   {
+      fileName = dirName + d->d_name;
+      if( stat(fileName.c_str(), &buf) != 0 )
+      {
+         const char *str = strerror(errno);
+         gdcmErrorMacro( str );
+      }
+      if ( S_ISREG(buf.st_mode) )    //is it a regular file?
+      {
+         Filenames.push_back( fileName );
+         numberOfFiles++;
+      }
+      else if ( S_ISDIR(buf.st_mode) ) //directory?
+      {
+         if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
+         {
+            numberOfFiles += Explore( fileName, recursive);
+         }
+      }
+      else
+      {
+         gdcmErrorMacro( "Unexpected error" );
+         return -1;
+      }
+   }
+   if( closedir(dir) != 0 )
+   {
+      const char *str = strerror(errno);
+      gdcmErrorMacro( str );
+   }
+#endif
+
+  return numberOfFiles;
+}
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Print method
+ * @param os ostream to write to 
+ */
+void DirList::Print(std::ostream &os, std::string const &)
+{
+   std::copy(Filenames.begin(), Filenames.end(), 
+             std::ostream_iterator<std::string>(os, "\n"));
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDirList.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDirList.h
new file mode 100644
index 0000000000000000000000000000000000000000..0069e889e1ba8ce268b094e79c8fcf6ca56ef16e
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDirList.h
@@ -0,0 +1,68 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDirList.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDIRLIST_H
+#define GDCMDIRLIST_H
+
+#include "gdcmCommon.h"
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+namespace gdcm 
+{
+
+typedef std::vector<std::string> DirListType;
+
+//-----------------------------------------------------------------------------
+
+// NOTE: Due to a M$VC6 'feature' we cannot export a std::list in a dll, 
+// so GDCM_EXPORT keyword was removed for this class only
+
+/**
+ * \brief   List containing the file headers of all the 'gdcm readable' files
+ *          found by exploring (possibly recursively) a root directory. 
+ */
+class GDCM_EXPORT DirList
+{
+public :
+   DirList(std::string const &dirName, bool recursive=false);
+   ~DirList();
+
+   void Print(std::ostream &os = std::cout, std::string const &indent = "" );
+
+   /// Return the name of the directory
+   std::string const &GetDirName() const { return DirName; }
+
+   /// Return the file names
+   DirListType const &GetFilenames() const { return Filenames; }
+
+   static bool IsDirectory(std::string const &dirName);
+
+private :
+   int Explore(std::string const &dirName, bool recursive=false);
+
+   /// List of file names
+   DirListType Filenames;
+   /// name of the root directory to explore
+   std::string DirName;
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntry.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntry.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6a2db24de6440ce628e6bbbe1801346075b3e598
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntry.cxx
@@ -0,0 +1,298 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDocEntry.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.8 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDocEntry.h"
+#include "gdcmTS.h"
+#include "gdcmVR.h"
+#include "gdcmGlobal.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+
+#include <iomanip> // for std::ios::left, ...
+#include <fstream>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+
+// Constructor / Destructor
+/**
+ * \brief   Constructor from a given DictEntry
+ * @param   in Pointer to existing dictionary entry
+ */
+DocEntry::DocEntry(DictEntry *in)
+{
+   ImplicitVR = false;
+   DicomDict  = in;
+   SetKey( in->GetKey( ) );
+   Offset     = 0 ; // To avoid further missprinting
+
+   // init some variables
+   ReadLength = 0;
+   Length = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Writes the common part of any ValEntry, BinEntry, SeqEntry
+ * @param fp already open ofstream pointer
+ * @param filetype type of the file (ACR, ImplicitVR, ExplicitVR, ...)
+ */
+void DocEntry::WriteContent(std::ofstream *fp, FileType filetype)
+{
+   uint32_t ffff  = 0xffffffff;
+   uint16_t group = GetGroup();
+
+   ///\todo allow skipping Shadow groups 
+ 
+   VRKey vr       = GetVR();
+   uint16_t elem    = GetElement();
+   uint32_t lgth  = GetLength();
+
+   if ( group == 0xfffe && elem == 0x0000 )
+   {
+     // Fix in order to make some MR PHILIPS images e-film readable
+     // see gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm:
+     // we just *always* ignore spurious fffe|0000 tag !   
+      return;
+   }
+
+   //
+   // ----------- Writes the common part
+   //
+   binary_write( *fp, group); //group number
+   binary_write( *fp, elem);  //element number
+
+   // Dicom V3 group 0x0002 is *always* Explicit VR !
+   if ( filetype == ExplicitVR || filetype == JPEG || group == 0x0002 )
+   {
+// ----------- Writes the common part : the VR + the length 
+
+      // Special case of delimiters:
+      if (group == 0xfffe)
+      {
+         // Delimiters have NO Value Representation
+         // Hence we skip writing the VR.
+         //
+         // In order to avoid further troubles, we choose to write them
+         // as 'no-length' Item Delimitors (we pad by writing 0xffffffff)
+         // We shall force the end of a given SeqItem by writting 
+         //  a Item Delimitation Item (fffe, e00d)
+
+         uint32_t ff = 0xffffffff;
+         binary_write(*fp, ff);
+         return;
+      }
+
+      uint16_t zero = 0;
+      uint16_t shortLgr = (uint16_t)lgth;
+
+      if (vr == GDCM_UNKNOWN)
+      {
+         // GDCM_UNKNOWN was stored in the Entry VR;
+         // deal with Entry as if TS were Implicit VR
+ 
+         binary_write(*fp, lgth);
+      }
+      else
+      {
+         binary_write(*fp, vr);
+         gdcmAssertMacro( vr.size() == 2 );
+                  
+         // See PS 3.5-2004 page 33, 36                  
+         if ( (vr == "SQ") || (vr == "OB") || (vr == "OW") || (vr == "OF") 
+          ||  (vr == "UN") || (vr == "UT") )
+         {
+            binary_write(*fp, zero);
+            if (vr == "SQ")
+            {
+               // we set SQ length to ffffffff
+               // and  we shall write a Sequence Delimitor Item 
+               // at the end of the Sequence! 
+               binary_write(*fp, ffff);
+            }
+            else
+            {
+               binary_write(*fp, lgth);
+            }
+         }
+         else
+         {
+            binary_write(*fp, shortLgr);
+         }
+      }
+   } 
+   else // IMPLICIT VR 
+   { 
+// ----------- Writes the common part : the VR  
+      if (vr == "SQ")
+      {
+         binary_write(*fp, ffff);
+      }
+      else
+      {
+         binary_write(*fp, lgth);
+      }
+   }
+}
+
+/**
+ * \brief   Gets the full length of the elementary DocEntry (not only value
+ *          length) depending on the VR.
+ */
+uint32_t DocEntry::GetFullLength()
+{
+   uint32_t l = GetReadLength();
+   if ( IsImplicitVR() )
+   {
+      l = l + 8;  // 2 (gr) + 2 (el) + 4 (lgth) 
+   }
+   else
+   {
+      if ( GetVR()=="OB" || GetVR()=="OW" || GetVR()=="SQ" )
+      {
+         l = l + 12; // 2 (gr) + 2 (el) + 2 (vr) + 2 (unused) + 4 (lgth)
+      }
+      else
+      {
+         l = l + 8;  // 2 (gr) + 2 (el) + 2 (vr) + 2 (lgth)
+      }
+   }
+   return l;
+}
+
+/**
+ * \brief   tells us if entry is the last one of a 'no length' SequenceItem 
+ *          (fffe,e00d) 
+ */
+bool DocEntry::IsItemDelimitor()
+{
+   return (GetGroup() == 0xfffe && GetElement() == 0xe00d);
+}
+
+/**
+ * \brief   tells us if entry is the first one of an Item 
+ *          (fffe,e000) 
+ */
+bool DocEntry::IsItemStarter()
+{
+   return (GetGroup() == 0xfffe && GetElement() == 0xe000);
+}
+
+/**
+ * \brief   tells us if entry is the last one of a 'no length' Sequence 
+ *          (fffe,e0dd) 
+ */
+bool DocEntry::IsSequenceDelimitor()
+{
+   return (GetGroup() == 0xfffe && GetElement() == 0xe0dd);
+}
+
+/**
+ * \brief Copies all the attributes from an other DocEntry 
+ * @param doc entry to copy from
+ */
+void DocEntry::Copy(DocEntry *doc)
+{
+   Length     = doc->Length;
+   ReadLength = doc->ReadLength;
+   ImplicitVR = doc->ImplicitVR;
+   Offset     = doc->Offset;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Prints the common part of ValEntry, BinEntry, SeqEntry
+ * @param   os ostream we want to print in
+ * @param indent Indentation string to be prepended during printing
+ */
+void DocEntry::Print(std::ostream &os, std::string const & )
+{
+   size_t o;
+   std::string st;
+   TSKey v;
+   std::string d2, vr;
+   itksys_ios::ostringstream s;
+   uint32_t lgth;
+
+   o  = GetOffset();
+   vr = GetVR();
+   if ( vr==GDCM_UNKNOWN )
+      vr = "  ";
+
+   s << DictEntry::TranslateToKey(GetGroup(),GetElement()); 
+
+   if (PrintLevel >= 2)
+   {
+      s << " lg : ";
+      lgth = GetReadLength(); // ReadLength, as opposed to (usable) Length
+      if (lgth == 0xffffffff)
+      {
+         st = " ffff ";
+         s.setf(std::ios::left);
+         s << std::setw(4);  
+         s << "    x(ffff) ";
+         s.setf(std::ios::left);
+         s << std::setw(8) << "-1"; 
+      }
+      else
+      {
+         st = Util::Format("x(%x)",lgth); // we may keep it
+         s.setf(std::ios::left);
+         s << std::setw(11-st.size()) << " ";
+         s << st << " ";
+         s.setf(std::ios::left);
+         s << std::setw(8) << lgth; 
+      }
+      s << " Off.: ";
+      st = Util::Format("x(%x)",o);  // we may keep it
+      s << std::setw(11-st.size()) << " ";
+      s << st << " ";
+      s << std::setw(8) << o; 
+   }
+   if (PrintLevel >= 1)
+      s << " ";
+
+   s << "[" << vr  << "] ";
+
+   std::string name;
+   if ( GetElement() == 0x0000 )
+      name = "Group Length";
+   else
+      name = GetName();
+
+   if (PrintLevel >= 1)
+   {
+      s.setf(std::ios::left);
+      s << std::setw(66-name.length()) << " ";
+   }
+    
+   s << "[" << name << "]";
+   os << s.str();      
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntry.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntry.h
new file mode 100644
index 0000000000000000000000000000000000000000..f43c74be764fb24727f7cebce038a7bb9aba3775
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntry.h
@@ -0,0 +1,162 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDocEntry.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 17:53:28 $
+  Version:   $Revision: 1.6 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDOCENTRY_H
+#define GDCMDOCENTRY_H
+
+#include "gdcmBase.h"
+#include "gdcmDictEntry.h"
+
+#include <iostream>
+#include <fstream>
+
+namespace gdcm 
+{
+class File;
+class ValEntry;
+class BinEntry;
+class SeqEntry;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief   The dicom header of a Dicom file contains a set of such entries
+ *          (when successfuly parsed against a given Dicom dictionary)
+ */
+class GDCM_EXPORT DocEntry : public Base
+{
+public:
+   DocEntry(DictEntry*);
+   /// \brief Canonical Destructor
+   virtual ~DocEntry() {}
+
+   virtual void Print (std::ostream &os = std::cout, std::string const &indent = ""); 
+   virtual void WriteContent(std::ofstream *fp, FileType filetype);
+
+   /// \brief  Gets the DicEntry of the current Dicom entry
+   /// @return The DicEntry of the current Dicom entry
+   DictEntry * GetDictEntry() { return DicomDict; } 
+
+   /// Returns the Dicom Group number of the current Dicom entry
+   uint16_t GetGroup() const { return DicomDict->GetGroup();  }
+
+   /// Returns the Dicom Element number of the current Dicom entry
+   uint16_t GetElement() const { return DicomDict->GetElement();}
+
+   /// Set the 'key' of the current Dicom entry
+   void  SetKey( TagKey const &key ) { Key = key; }
+
+   /// Returns the 'key' of the current Dicom entry
+   TagKey const &GetKey() const { return Key; }
+
+   /// \brief Returns the 'Name' '(e.g. "Patient's Name") found in the Dicom
+   /// Dictionnary of the current Dicom Header Entry
+   std::string const &GetName() const { return DicomDict->GetName(); }
+
+   /// \brief Returns the 'Value Representation' (e.g. "PN" : Person Name,
+   /// "SL" : Signed Long), found in the Dicom header or in the Dicom
+   /// Dictionnary, of the current Dicom entry
+   std::string const &GetVR() const { return DicomDict->GetVR(); }
+
+   /// \brief Returns the 'Value Multiplicity' (e.g. "1", "6", "1-n", "3-n"),
+   /// found in the Dicom entry or in the Dicom Dictionnary
+   /// of the current Dicom entry
+   std::string const &GetVM() const { return DicomDict->GetVM(); }
+
+   /// Sets the 'Value Multiplicity' of the current Dicom entry
+   void SetVM( TagName const &v) { DicomDict->SetVM(v); } 
+
+   /// \brief Returns offset (since the beginning of the file, including
+   /// the File Preamble, if any) of the value of the current Dicom entry
+   /// \warning offset of the *value*, not of the Dicom entry
+   const size_t &GetOffset() const { return Offset; }
+
+   /// \brief Sets only 'Read Length' (*not* 'Usable Length') of the current
+   /// Dicom entry
+   void SetReadLength(uint32_t l) { ReadLength = l; }
+   /// \brief Returns the 'read length' of the current Dicom entry
+   /// \warning this value is the one stored in the Dicom header but not
+   ///          mandatoryly the one thats's used (in case on SQ, or delimiters,
+   ///          the usable length is set to zero)
+   const uint32_t &GetReadLength() const { return ReadLength; }
+
+   /// \brief Sets both 'Read Length' and 'Usable Length' of the current
+   /// Dicom entry
+   virtual void SetLength(uint32_t l) { Length = l; }
+   /// \brief Returns the actual value length of the current Dicom entry
+   /// \warning this value is not *always* the one stored in the Dicom header
+   ///          in case of well known bugs
+   const uint32_t &GetLength() const { return Length; }
+
+   uint32_t GetFullLength();
+   virtual uint32_t ComputeFullLength() = 0;
+
+// The following 3 members, for internal use only ! 
+   /// \brief   Sets the offset of the Dicom entry
+   /// \warning use with caution !
+   /// @param   of offset to be set
+   void SetOffset(size_t of) { Offset = of; }
+
+   /// Sets to TRUE the ImplicitVr flag of the current Dicom entry
+   void SetImplicitVR() { ImplicitVR = true; }
+ 
+   /// \brief Tells us if the current Dicom entry was checked as ImplicitVr
+   /// @return true if the current Dicom entry was checked as ImplicitVr
+   bool IsImplicitVR() const { return ImplicitVR; }
+
+   /// \brief Tells us if the VR of the current Dicom entry is Unknown
+   /// @return true if the VR is unknown
+   bool IsVRUnknown() const { return DicomDict->IsVRUnknown(); }
+
+   /// \brief Tells us if the VM of the current Dicom entry is Unknown
+   /// @return true if the VM is unknown
+   bool IsVMUnknown() const { return DicomDict->IsVMUnknown(); }
+
+   bool IsItemDelimitor();
+   bool IsItemStarter();
+   bool IsSequenceDelimitor();   
+
+   virtual void Copy(DocEntry *e);
+
+protected:
+   /// \brief pointer to the underlying Dicom dictionary element
+   DictEntry *DicomDict;
+   
+   /// \brief Correspond to the real length of the data
+   /// This length might always be even
+   uint32_t Length; 
+  
+   /// \brief Length to read in the file to obtain data
+   uint32_t ReadLength;
+
+   /// \brief Even when reading explicit vr files, some elements happen to
+   /// be implicit. Flag them here since we can't use the entry->vr without
+   /// breaking the underlying dictionary.
+   bool ImplicitVR;
+
+   /// Offset from the beginning of file for direct user access
+   size_t Offset; 
+
+   /// \brief Generalized key of this DocEntry (for details on
+   ///        the generalized key refer to \ref TagKey documentation).
+   TagKey Key;
+
+private:
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntryArchive.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntryArchive.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3a5e0738918fa115ee663fd4c717fd1e8d4fd340
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntryArchive.cxx
@@ -0,0 +1,175 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDocEntryArchive.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDocEntryArchive.h"
+#include "gdcmDebug.h"
+#include "gdcmDocEntry.h"
+
+#include <string>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief Constructor
+ */
+DocEntryArchive::DocEntryArchive(File *file)
+{
+   ArchFile = file;
+}
+
+/**
+ * \brief Destructor
+ */
+DocEntryArchive::~DocEntryArchive()
+{
+   ClearArchive();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Replaces in the Header a DocEntry by the new DocEntry. 
+ *          The initial DocEntry is kept in archive.
+ * @param   newEntry New entry to substitute to an other entry of the Header
+ * @return  FALSE when an other DocEntry is already archived with the same key
+ *          TRUE otherwise
+ */
+bool DocEntryArchive::Push(DocEntry *newEntry)
+{
+   if ( !newEntry )
+      return false;
+
+   uint16_t group = newEntry->GetDictEntry()->GetGroup();
+   uint16_t elem  = newEntry->GetDictEntry()->GetElement();
+   TagKey key = DictEntry::TranslateToKey(group,elem);
+
+   if ( Archive.find(key) == Archive.end() )
+   {
+      // Save the old DocEntry if any
+      DocEntry *old = ArchFile->GetDocEntry(group, elem);
+      Archive[key]  = old;
+      if ( old )
+         ArchFile->RemoveEntryNoDestroy(old);
+
+      // Set the new DocEntry
+      ArchFile->AddEntry(newEntry);
+
+      return true;
+   }
+   return false;
+}
+
+/**
+ * \brief   Removes out of the Header a DocEntry.
+ *          (it's kept in archive).
+ * @param   group   Group number of the Entry to remove
+ * @param   elem  Element number of the Entry to remove
+ * @return  FALSE when an other DocEntry is already archived with the same key
+ *          TRUE otherwise
+ */
+bool DocEntryArchive::Push(uint16_t group, uint16_t elem)
+{
+   TagKey key = DictEntry::TranslateToKey(group, elem);
+
+   if ( Archive.find(key)==Archive.end() )
+   {
+      // Save the old DocEntry if any
+      DocEntry *old = ArchFile->GetDocEntry(group, elem);
+      Archive[key] = old;
+      if ( old )
+         ArchFile->RemoveEntryNoDestroy(old);
+
+      return true;
+   }
+   return false;
+}
+
+/**
+ * \brief   Restore in the Header the DocEntry specified by (group,element). 
+ *          The archive entry is destroyed.
+ * @param   group   Group number of the Entry to restore
+ * @param   elem  Element number of the Entry to restore
+ * @return  FALSE when the key isn't in the archive, 
+ *          TRUE otherwise
+ */
+bool DocEntryArchive::Restore(uint16_t group, uint16_t elem)
+{
+   TagKey key=DictEntry::TranslateToKey(group, elem);
+
+   TagDocEntryHT::iterator restoreIt=Archive.find(key);
+   if ( restoreIt!=Archive.end() )
+   {
+      // Delete the new value
+      DocEntry *rem = ArchFile->GetDocEntry(group, elem);
+      if ( rem )
+         ArchFile->RemoveEntry(rem);
+
+      // Restore the old value
+      if ( Archive[key] )
+         ArchFile->AddEntry(Archive[key]);
+
+      Archive.erase(restoreIt);
+
+      return true;
+   }
+   return false;
+}
+
+/**
+ * \brief   Removes all DocEntry from the archive, and destroy them.  
+ *          The archives entries aren't restored.
+ */
+void DocEntryArchive::ClearArchive( )
+{
+   for(TagDocEntryHT::iterator it = Archive.begin();
+       it!=Archive.end();
+       ++it)
+   {
+      delete it->second;
+   }
+   Archive.clear();
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Print all 
+ * @param   os The output stream to be written to.
+ */
+void DocEntryArchive::Print(std::ostream &os) 
+{
+   os << "Elements in archives :" << std::endl;
+   for(TagDocEntryHT::iterator it = Archive.begin();
+       it!=Archive.end();
+       ++it)
+   {
+      if ( it->second )
+         it->second->Print(os);
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntryArchive.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntryArchive.h
new file mode 100644
index 0000000000000000000000000000000000000000..547bd1abcf36629e9bb954f107107ba3c0dc4da4
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntryArchive.h
@@ -0,0 +1,62 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDocEntryArchive.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDOCENTRYARCHIVE_H
+#define GDCMDOCENTRYARCHIVE_H
+
+#include "gdcmFile.h"
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief Container 
+ * It's goal is to change the File header correctly. At this time, the change is 
+ * only made for the first level of the Document. In the future, it might 
+ * consider Dicom Sequences (SeqEntry, within any SQItem).
+ * The change is made by replacing a DocEntry by an other that is created
+ * outside the class. The old value is kept. When we restore the File
+ * status, the added DocEntry is deleted and replaced by the old value.
+ */
+class GDCM_EXPORT DocEntryArchive 
+{
+
+friend class FileHelper;
+
+private:
+   DocEntryArchive(File *file);
+   ~DocEntryArchive();
+
+   void Print(std::ostream &os = std::cout);
+
+   bool Push(DocEntry *newEntry);
+   bool Push(uint16_t group,uint16_t elem);
+   bool Restore(uint16_t group,uint16_t elem);
+
+   void ClearArchive(void);
+
+   /// pointer to the gdcm::File pointer we want to save values from
+   File *ArchFile;
+   /// H table to save values.
+   TagDocEntryHT Archive;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntrySet.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntrySet.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..156ad47ef18050086ab1c6f8b3798c2b122cc723
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntrySet.cxx
@@ -0,0 +1,639 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDocEntrySet.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+#include "gdcmDocEntrySet.h"
+
+#include "gdcmDebug.h"
+#include "gdcmCommon.h"
+#include "gdcmDictSet.h"
+#include "gdcmGlobal.h"
+#include "gdcmDocEntry.h"
+#include "gdcmSeqEntry.h"
+#include "gdcmValEntry.h"
+#include "gdcmBinEntry.h"
+#include "gdcmUtil.h"
+#if defined(__BORLANDC__)
+   #include <mem.h> // for memset
+#endif 
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+DocEntrySet::DocEntrySet() 
+{ 
+   PreviousDocEntry = 0;
+}
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Get the "std::string representable" value of the Dicom entry
+ * @param   group  Group number of the searched tag.
+ * @param   elem Element number of the searched tag.
+ * @return  Corresponding element value when it exists,
+ *          and the string GDCM_UNFOUND otherwise.
+ */
+std::string DocEntrySet::GetEntryValue(uint16_t group, uint16_t elem)
+{
+   ContentEntry *entry = dynamic_cast<ContentEntry *>(GetDocEntry(group,elem));
+   if ( entry )
+      return entry->GetValue();
+   return GDCM_UNFOUND;
+}
+
+/**
+ * \brief   Gets (from Header) a 'non string' element value 
+ * @param group   group number of the Entry 
+ * @param elem  element number of the Entry
+ * @return Pointer to the 'non string' area
+ */
+void *DocEntrySet::GetEntryBinArea(uint16_t group, uint16_t elem) 
+{
+   BinEntry *entry = GetBinEntry(group, elem);
+   if ( entry )
+      return entry->GetBinArea();
+   return 0;
+}
+
+/**
+ * \brief   Return the value of the BinEntry if it's "std::string representable"
+ * @param   group  Group number of the searched tag.
+ * @param   elem Element number of the searched tag.
+ * @return  Corresponding element value when it's "std::string representable"
+ *          and the string GDCM_NOTASCII otherwise.
+ */
+std::string DocEntrySet::GetEntryForcedAsciiValue(uint16_t group, uint16_t elem)
+{
+   DocEntry *d = GetDocEntry(group,elem);
+   if ( !d )
+      return GDCM_UNFOUND;
+
+   if (ValEntry *v = dynamic_cast<ValEntry *>(d))
+      return v->GetValue();
+
+   if (BinEntry *b = dynamic_cast<BinEntry *>(d))
+   {
+      uint8_t *a = b->GetBinArea();
+      if (!b)
+         return GDCM_NOTLOADED;
+         // TODO : unify those two methods.
+      if (Util::IsCleanArea(a, b->GetLength()) )
+         return  Util::CreateCleanString(a, b->GetLength());
+   }
+   return GDCM_NOTASCII;
+}
+
+/**
+ * \brief   Searches within Header Entries (Dicom Elements) parsed with 
+ *          the public and private dictionaries 
+ *          for the value length of a given tag..
+ * @param   group  Group number of the searched tag.
+ * @param   elem Element number of the searched tag.
+ * @return  Corresponding element length; -1 if not found
+ */
+int DocEntrySet::GetEntryLength(uint16_t group, uint16_t elem)
+{
+   DocEntry *entry = GetDocEntry(group, elem);
+   if ( entry )
+      return entry->GetLength();
+   return -1;
+}
+
+/**
+ * \brief   Searches within Header Entries (Dicom Elements) parsed with 
+ *          the public [and private dictionaries] 
+ *          for the element value representation of a given tag..
+ *          Obtaining the VR (Value Representation) might be needed by caller
+ *          to convert the string typed content to caller's native type 
+ *          (think of C++ vs Python). The VR is actually of a higher level
+ *          of semantics than just the native C++ type.
+ * @param   group  Group number of the searched tag.
+ * @param   elem Element number of the searched tag.
+ * @return  Corresponding element value representation when it exists,
+ *          and the string GDCM_UNFOUND ("gdcm::Unfound") otherwise.
+ */
+std::string DocEntrySet::GetEntryVR(uint16_t group, uint16_t elem)
+{
+   DocEntry *entry = GetDocEntry(group, elem);
+   if ( entry )
+      return entry->GetVR();
+   return GDCM_UNFOUND;
+}
+
+/**
+ * \brief  Same as \ref Document::GetDocEntry except it only
+ *         returns a result when the corresponding entry is of type
+ *         ValEntry.
+ * @param   group  Group number of the searched Dicom Element 
+ * @param   elem Element number of the searched Dicom Element  
+ * @return When present, the corresponding ValEntry. 
+ */
+ValEntry *DocEntrySet::GetValEntry(uint16_t group, uint16_t elem)
+{
+   DocEntry *currentEntry = GetDocEntry(group, elem);
+   if ( !currentEntry )
+      return NULL;
+
+   return dynamic_cast<ValEntry*>(currentEntry);
+}
+
+/**
+ * \brief  Same as \ref Document::GetDocEntry except it only
+ *         returns a result when the corresponding entry is of type
+ *         BinEntry.
+ * @param   group  Group number of the searched Dicom Element
+ * @param   elem Element number of the searched Dicom Element
+ * @return When present, the corresponding BinEntry. 
+ */
+BinEntry *DocEntrySet::GetBinEntry(uint16_t group, uint16_t elem)
+{
+   DocEntry *currentEntry = GetDocEntry(group, elem);
+   if ( !currentEntry )
+   {
+      gdcmWarningMacro( "No corresponding BinEntry " << std::hex << group <<
+                         "," << elem);
+      return NULL;
+   }
+
+   return dynamic_cast<BinEntry*>(currentEntry);
+}
+
+/**
+ * \brief  Same as \ref Document::GetDocEntry except it only
+ *         returns a result when the corresponding entry is of type
+ *         SeqEntry.
+ * @param   group  Group number of the searched Dicom Element 
+ * @param   elem Element number of the searched Dicom Element  
+ * @return When present, the corresponding SeqEntry. 
+ */
+SeqEntry *DocEntrySet::GetSeqEntry(uint16_t group, uint16_t elem)
+{
+   DocEntry *currentEntry = GetDocEntry(group, elem);
+   if ( !currentEntry )
+   {
+      gdcmWarningMacro( "No corresponding SeqEntry " << std::hex << group <<
+                        "," << elem);
+      return NULL;
+   }
+
+   return dynamic_cast<SeqEntry*>(currentEntry);
+}
+
+/**
+ * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
+ *          through it's (group, element) and modifies it's content with
+ *          the given value.
+ * @param   content new value (string) to substitute with
+ * @param   group  group number of the Dicom Element to modify
+ * @param   elem element number of the Dicom Element to modify
+ */
+bool DocEntrySet::SetValEntry(std::string const &content, 
+                              uint16_t group, uint16_t elem) 
+{
+   ValEntry *entry = GetValEntry(group, elem);
+   if (!entry )
+   {
+      gdcmWarningMacro( "No corresponding ValEntry " << std::hex << group <<
+                         "," << elem << " element (try promotion first).");
+      return false;
+   }
+   return SetValEntry(content,entry);
+}
+
+/**
+ * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
+ *          through it's (group, element) and modifies it's content with
+ *          the given value.
+ * @param   content new value (void*  -> uint8_t*) to substitute with
+ * @param   lgth new value length
+ * @param   group  group number of the Dicom Element to modify
+ * @param   elem element number of the Dicom Element to modify
+ */
+bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth, 
+                              uint16_t group, uint16_t elem) 
+{
+   BinEntry *entry = GetBinEntry(group, elem);
+   if (!entry )
+   {
+      gdcmWarningMacro( "No corresponding ValEntry " << std::hex << group <<
+                        "," << elem << " element (try promotion first).");
+      return false;
+   }
+
+   return SetBinEntry(content,lgth,entry);
+} 
+
+/**
+ * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
+ *          and modifies it's content with the given value.
+ * @param  content new value (string) to substitute with
+ * @param  entry Entry to be modified
+ */
+bool DocEntrySet::SetValEntry(std::string const &content, ValEntry *entry)
+{
+   if (entry)
+   {
+      entry->SetValue(content);
+      return true;
+   }
+   return false;
+}
+
+/**
+ * \brief   Accesses an existing BinEntry (i.e. a Dicom Element)
+ *          and modifies it's content with the given value.
+ * @param   content new value (void*  -> uint8_t*) to substitute with
+ * @param  entry Entry to be modified 
+ * @param  lgth new value length
+ */
+bool DocEntrySet::SetBinEntry(uint8_t *content, int lgth, BinEntry *entry)
+{
+   if (entry)
+   {
+      entry->SetBinArea(content);  
+      entry->SetLength(lgth);
+      entry->SetValue(GDCM_BINLOADED);
+      return true;
+   }
+   return false;
+}
+
+/**
+ * \brief   Modifies the value of a given Doc Entry (Dicom Element)
+ *          when it exists. Create it with the given value when unexistant.
+ * @param   value (string) Value to be set
+ * @param   group   Group number of the Entry 
+ * @param   elem  Element number of the Entry
+ * @param   vr  V(alue) R(epresentation) of the Entry -if private Entry-
+ * \return  pointer to the modified/created Header Entry (NULL when creation
+ *          failed).
+ */ 
+ValEntry *DocEntrySet::InsertValEntry(std::string const &value, 
+                                      uint16_t group, uint16_t elem,
+                                      TagName const &vr )
+{
+   ValEntry *valEntry = 0;
+   DocEntry *currentEntry = GetDocEntry( group, elem );
+   
+   if (currentEntry)
+   {
+      valEntry = dynamic_cast<ValEntry *>(currentEntry);
+
+      // Verify the VR
+      if ( valEntry )
+         if ( valEntry->GetVR()!=vr )
+            valEntry = NULL;
+
+      // if currentEntry doesn't correspond to the requested valEntry
+      if ( !valEntry)
+      {
+         if ( !RemoveEntry(currentEntry) )
+         {
+            gdcmWarningMacro( "Removal of previous DocEntry failed.");
+            return NULL;
+         }
+      }
+   }
+
+   // Create a new valEntry if necessary
+   if ( !valEntry )
+   {
+      valEntry = NewValEntry( group, elem, vr );
+
+      if ( !AddEntry(valEntry) )
+      {
+         gdcmWarningMacro("AddEntry failed although this is a creation.");
+         delete valEntry;
+         return NULL;
+      }
+   }
+
+   // Set the binEntry value
+   SetValEntry(value, valEntry); // The std::string value
+   return valEntry;
+}
+
+/**
+ * \brief   Modifies the value of a given Header Entry (Dicom Element)
+ *          when it exists. Create it with the given value when unexistant.
+ *          A copy of the binArea is made to be kept in the Document.
+ * @param   binArea (binary) value to be set
+ * @param   lgth length of the Bin Area we want to set
+ * @param   group   Group number of the Entry 
+ * @param   elem  Element number of the Entry
+ * @param   vr  V(alue) R(epresentation) of the Entry -if private Entry-
+ * \return  pointer to the modified/created Header Entry (NULL when creation
+ *          failed).
+ */
+BinEntry *DocEntrySet::InsertBinEntry(uint8_t *binArea, int lgth, 
+                                      uint16_t group, uint16_t elem,
+                                      TagName const &vr )
+{
+   BinEntry *binEntry = 0;
+   DocEntry *currentEntry = GetDocEntry( group, elem );
+
+   // Verify the currentEntry
+   if (currentEntry)
+   {
+      binEntry = dynamic_cast<BinEntry *>(currentEntry);
+
+      // Verify the VR
+      if ( binEntry )
+         if ( binEntry->GetVR()!=vr )
+            binEntry = NULL;
+
+      // if currentEntry doesn't correspond to the requested valEntry
+      if ( !binEntry)
+      {
+         if ( !RemoveEntry(currentEntry) )
+         {
+            gdcmWarningMacro( "Removal of previous DocEntry failed.");
+            return NULL;
+         }
+      }
+   }
+
+   // Create a new binEntry if necessary
+   if ( !binEntry)
+   {
+      binEntry = NewBinEntry(group, elem, vr);
+
+      if ( !AddEntry(binEntry) )
+      {
+         gdcmWarningMacro( "AddEntry failed although this is a creation.");
+         delete binEntry;
+         return NULL;
+      }
+   }
+
+   // Set the binEntry value
+   uint8_t *tmpArea;
+   if ( lgth>0 && binArea )
+   {
+      tmpArea = new uint8_t[lgth];
+      memcpy(tmpArea,binArea,lgth);
+   }
+   else
+   {
+      tmpArea = 0;
+   }
+   if ( !SetBinEntry(tmpArea,lgth,binEntry) )
+   {
+      if ( tmpArea )
+      {
+         delete[] tmpArea;
+      }
+   }
+   return binEntry;
+}  
+
+/**
+ * \brief   Creates a new gdcm::SeqEntry and adds it to the current DocEntrySet.
+ *          (remove any existing entry with same group,elem)
+ * @param   group   Group number of the Entry 
+ * @param   elem  Element number of the Entry
+ * \return  pointer to the created SeqEntry (NULL when creation
+ *          failed).
+ */
+SeqEntry *DocEntrySet::InsertSeqEntry(uint16_t group, uint16_t elem)
+{
+   SeqEntry *seqEntry = 0;
+   DocEntry *currentEntry = GetDocEntry( group, elem );
+
+   // Verify the currentEntry
+   if ( currentEntry )
+   {
+      seqEntry = dynamic_cast<SeqEntry *>(currentEntry);
+
+      // Verify the VR
+      if ( seqEntry )
+         seqEntry = NULL;
+
+      // if currentEntry doesn't correspond to the requested seqEntry
+      if ( !seqEntry )
+      {
+         if (!RemoveEntry(currentEntry))
+         {
+            gdcmWarningMacro( "Removal of previous DocEntry failed.");
+
+            return NULL;
+         }
+      }
+   }
+   // Create a new seqEntry if necessary
+   if ( !seqEntry )
+   {
+      seqEntry = NewSeqEntry(group, elem);
+
+      if ( !AddEntry(seqEntry) )
+      {
+         gdcmWarningMacro( "AddEntry failed although this is a creation.");
+
+         delete seqEntry;
+         return NULL;
+      }
+   }
+
+   // TODO : Find a trick to insert a SequenceDelimitationItem 
+   //       in the SeqEntry, at the end.
+   return seqEntry;
+} 
+ 
+/**
+ * \brief   Checks if a given Dicom Element exists within the DocEntrySet
+ * @param   group   Group number of the searched Dicom Element 
+ * @param   elem  Element number of the searched Dicom Element 
+ * @return true is found
+ */
+bool DocEntrySet::CheckIfEntryExist(uint16_t group, uint16_t elem )
+{
+   return GetDocEntry(group,elem)!=NULL;
+}
+
+/**
+ * \brief   Build a new Val Entry from all the low level arguments. 
+ *          Check for existence of dictionary entry, and build
+ *          a default one when absent.
+ * @param   group Group number   of the new Entry
+ * @param   elem  Element number of the new Entry
+ * @param   vr    V(alue) R(epresentation) of the new Entry 
+ */
+ValEntry *DocEntrySet::NewValEntry(uint16_t group,uint16_t elem,
+                                   TagName const &vr) 
+{
+   DictEntry *dictEntry = GetDictEntry(group, elem, vr);
+   gdcmAssertMacro(dictEntry);
+
+   ValEntry *newEntry = new ValEntry(dictEntry);
+   if (!newEntry) 
+   {
+      gdcmWarningMacro( "Failed to allocate ValEntry");
+      return 0;
+   }
+   return newEntry;
+}
+
+
+/**
+ * \brief   Build a new Bin Entry from all the low level arguments. 
+ *          Check for existence of dictionary entry, and build
+ *          a default one when absent.
+ * @param   group Group   number of the new Entry
+ * @param   elem  Element number of the new Entry
+ * @param   vr    V(alue) R(epresentation) of the new Entry 
+ */
+BinEntry *DocEntrySet::NewBinEntry(uint16_t group, uint16_t elem,
+                                   TagName const &vr) 
+{
+   DictEntry *dictEntry = GetDictEntry(group, elem, vr);
+   gdcmAssertMacro(dictEntry);
+
+   BinEntry *newEntry = new BinEntry(dictEntry);
+   if (!newEntry) 
+   {
+      gdcmWarningMacro( "Failed to allocate BinEntry");
+      return 0;
+   }
+   return newEntry;
+}
+
+/**
+ * \brief   Build a new SeqEntry from all the low level arguments. 
+ *          Check for existence of dictionary entry, and build
+ *          a default one when absent.
+ * @param   group Group   number of the new Entry
+ * @param   elem  Element number of the new Entry
+ */
+SeqEntry* DocEntrySet::NewSeqEntry(uint16_t group, uint16_t elem) 
+{
+   DictEntry *dictEntry = GetDictEntry(group, elem, "SQ");
+   gdcmAssertMacro(dictEntry);
+
+   SeqEntry *newEntry = new SeqEntry( dictEntry );
+   if (!newEntry)
+   {
+      gdcmWarningMacro( "Failed to allocate SeqEntry");
+      return 0;
+   }
+   return newEntry;
+}
+
+/**
+ * \brief   Request a new virtual dict entry to the dict set
+ * @param   group Group   number of the underlying DictEntry
+ * @param   elem  Element number of the underlying DictEntry
+ * @param   vr    V(alue) R(epresentation) of the underlying DictEntry
+ * @param   vm    V(alue) M(ultiplicity)   of the underlying DictEntry
+ * @param   name   english name
+ */
+DictEntry* DocEntrySet::NewVirtualDictEntry( uint16_t group, uint16_t elem,
+                                             TagName const &vr,
+                                             TagName const &vm,
+                                             TagName const &name )
+{
+   return Global::GetDicts()->NewVirtualDictEntry(group,elem,vr,vm,name);
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+/**
+ * \brief   Searches [both] the public [and the shadow dictionary (when they
+ *          exist)] for the presence of the DictEntry with given
+ *          group and element. The public dictionary has precedence on the
+ *          shadow one(s), if any.
+ * @param   group  Group number of the searched DictEntry
+ * @param   elem Element number of the searched DictEntry
+ * @return  Corresponding DictEntry when it exists, NULL otherwise.
+ */
+DictEntry *DocEntrySet::GetDictEntry(uint16_t group,uint16_t elem) 
+{
+   DictEntry *found = 0;
+   Dict *pubDict = Global::GetDicts()->GetDefaultPubDict();
+   if (!pubDict) 
+   {
+      gdcmWarningMacro( "We SHOULD have a default dictionary");
+   }
+   else
+   {
+      found = pubDict->GetEntry(group, elem);
+   }
+   return found;
+}
+
+/**
+ * \brief   Searches [both] the public [and the shadow dictionary (when they
+ *          exist)] for the presence of the DictEntry with given
+ *          group and element, and create a new virtual DictEntry if necessary
+ * @param   group  group number of the searched DictEntry
+ * @param   elem element number of the searched DictEntry
+ * @param   vr V(alue) R(epresentation) to use, if necessary 
+ * @return  Corresponding DictEntry when it exists, NULL otherwise.
+ * \remarks The returned DictEntry is registered
+ */
+DictEntry *DocEntrySet::GetDictEntry(uint16_t group, uint16_t elem,
+                                     TagName const &vr)
+{
+   DictEntry *dictEntry = GetDictEntry(group,elem);
+   DictEntry *goodEntry = dictEntry;
+   std::string goodVR = vr;
+   TagName vm;
+   if (elem == 0x0000)
+      goodVR="UL";
+
+   if ( goodEntry )
+   {
+      if ( goodVR != goodEntry->GetVR()
+        && goodVR != GDCM_UNKNOWN )
+      {
+         gdcmWarningMacro("For (" << std::hex << group << "|"
+            << elem << "), found VR : [" << vr << "]"
+            << " expected: [" << goodEntry->GetVR() << "]" ) ;
+         // avoid confusing further validator with "FIXME" VM
+         // when possible      
+         vm = dictEntry->GetVM();
+         goodEntry = NULL;
+      }
+   }
+   else
+   {
+      vm = "FIXME";
+   }
+
+   // Create a new virtual DictEntry if necessary
+   if (!goodEntry)
+   {
+      if (dictEntry)
+      {
+         goodEntry = NewVirtualDictEntry(group, elem, goodVR, vm,
+                                         dictEntry->GetName() );
+      }
+      else
+      {
+         goodEntry = NewVirtualDictEntry(group, elem, goodVR);
+      }
+   }
+   return goodEntry;
+}
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntrySet.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntrySet.h
new file mode 100644
index 0000000000000000000000000000000000000000..db90f259131abdab32a85048a24473574d021d39
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDocEntrySet.h
@@ -0,0 +1,145 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDocEntrySet.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:38 $
+  Version:   $Revision: 1.5 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMDOCENTRYSET_H
+#define GDCMDOCENTRYSET_H
+
+#include "gdcmBase.h"
+#include <fstream>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+class DocEntry;
+class ValEntry;
+class BinEntry;
+class SeqEntry;
+class DictEntry;
+
+typedef TagKey BaseTagKey;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief
+ * \ref DocEntrySet is an abstract base class for \ref ElementSet
+ * and \ref SQItem which are both containers for DocEntries.
+ *  - \ref ElementSet is based on the STL map<> container
+ * (see \ref ElementSet::TagHT)
+ *  - \ref SQItem is based on an STL list container (see \ref ListDocEntry).
+ * 
+ * Since the syntax for adding a new element to a map<> or a list<>
+ * differ, \ref DocEntrySet is designed as an adapter to unify the
+ * interfaces of \ref DocEntrySet and \ref ElementSet.
+ * 
+ * As an illustration of this design, please refer to the implementation
+ * of \ref AddEntry (or any pure virtual method) in both derived classes.
+ * This adapter unification of interfaces enables the parsing of a
+ * DICOM header containing (optionaly heavily nested) sequences to be
+ * written recursively [see \ref Document::ParseDES 
+ * which calls \ref Document::ParseSQ, which in turn calls 
+ * \ref Document::ParseDES ].
+ *
+ * \note Developpers should strongly resist to the temptation of adding
+ *       members to this class since this class is designed as an adapter 
+ *       in the form of an abstract base class.
+ */
+class GDCM_EXPORT DocEntrySet : public Base
+{
+public:
+   /// Canonical Constructor
+   DocEntrySet();
+   /// Canonical Destructor
+   virtual ~DocEntrySet() {}
+
+   /// \brief write any type of entry to the entry set
+   virtual void WriteContent (std::ofstream *fp, FileType filetype) = 0;
+
+   /// \brief Remove all Entry of the current set
+   virtual void ClearEntry() = 0;
+   /// \brief adds any type of entry to the current set
+   virtual bool AddEntry(DocEntry *entry) = 0;
+   /// \brief Removes any type of entry out of the entry set, and destroys it
+   virtual bool RemoveEntry(DocEntry *entryToRemove) = 0;
+   /// \brief Removes any type of entry out of the entry set, DOESN'T destroy it
+   virtual bool RemoveEntryNoDestroy(DocEntry *entryToRemove) = 0;
+   /// \brief Gets the first entry (of any type) of the current set
+   virtual DocEntry *GetFirstEntry()=0;
+   /// \brief Gets the next entry (of any type) of the current set
+   virtual DocEntry *GetNextEntry()=0;
+
+   virtual std::string GetEntryValue(uint16_t group, uint16_t elem);
+   virtual void *GetEntryBinArea(uint16_t group, uint16_t elem);
+   
+   virtual int GetEntryLength(uint16_t group, uint16_t elem);
+   virtual std::string GetEntryVR(uint16_t group, uint16_t elem);
+   virtual std::string GetEntryForcedAsciiValue(uint16_t group, uint16_t elem);
+   /// \brief Gets any type of DocEntry, identified by its (group,elem)
+   virtual DocEntry *GetDocEntry(uint16_t group, uint16_t elem) = 0;
+   /// \brief Gets a ValEntry, identified by its (group, elem)
+   ValEntry *GetValEntry(uint16_t group, uint16_t elem);
+   /// \brief Gets a BinEntry, identified by its (group,elem)
+   BinEntry *GetBinEntry(uint16_t group, uint16_t elem);
+   /// \brief Gets a SeqEntry, identified by its (group,elem)
+   SeqEntry *GetSeqEntry(uint16_t group, uint16_t elem);
+
+   bool SetValEntry(std::string const &content,
+                    uint16_t group, uint16_t elem);
+   bool SetBinEntry(uint8_t *content, int lgth,
+                    uint16_t group, uint16_t elem);
+   bool SetValEntry(std::string const &content, ValEntry *entry);
+   bool SetBinEntry(uint8_t *content, int lgth, BinEntry *entry);
+
+   ValEntry *InsertValEntry(std::string const &value,
+                                    uint16_t group, uint16_t elem,
+                                    TagName const &vr = GDCM_UNKNOWN);
+   BinEntry *InsertBinEntry(uint8_t *binArea, int lgth,
+                                    uint16_t group, uint16_t elem,
+                                    TagName const &vr = GDCM_UNKNOWN);
+   SeqEntry *InsertSeqEntry(uint16_t group, uint16_t elem);
+   /// \brief Tells us if the set contains no entry
+   virtual bool IsEmpty() = 0;
+   virtual bool CheckIfEntryExist(uint16_t group, uint16_t elem);
+
+// DocEntry  related utilities 
+   ValEntry *NewValEntry(uint16_t group,uint16_t elem,
+                         TagName const &vr = GDCM_UNKNOWN);
+   BinEntry *NewBinEntry(uint16_t group, uint16_t elem,
+                         TagName const &vr = GDCM_UNKNOWN);
+   SeqEntry *NewSeqEntry(uint16_t group, uint16_t elem);
+
+// DictEntry  related utilities 
+   DictEntry *NewVirtualDictEntry(uint16_t group,uint16_t elem,
+                                  TagName const &vr     = GDCM_UNKNOWN,
+                                  TagName const &vm     = GDCM_UNKNOWN,
+                                  TagName const &name   = GDCM_UNKNOWN );
+
+protected:
+// DictEntry  related utilities
+   DictEntry *GetDictEntry(uint16_t group, uint16_t elem);
+   DictEntry *GetDictEntry(uint16_t group, uint16_t elem,
+                           TagName const &vr);
+   /// To be able to backtrack (Private Sequence, Implicit VR related pb)
+   DocEntry *PreviousDocEntry;
+
+private:
+};
+
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDocument.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmDocument.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ae5cb6a893abc497cf0ad9730cba1ae8358a767b
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDocument.cxx
@@ -0,0 +1,2462 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDocument.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.19 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDocument.h"
+#include "gdcmValEntry.h"
+#include "gdcmBinEntry.h"
+#include "gdcmSeqEntry.h"
+#include "gdcmGlobal.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+#include "gdcmTS.h"
+#include "gdcmDictSet.h"
+#include "gdcmDocEntrySet.h"
+#include "gdcmSQItem.h"
+
+#include <vector>
+#include <iomanip>
+#include <fstream>
+#include <ctype.h>  // for isdigit
+#include <stdlib.h> // for atoi
+
+#if defined(__BORLANDC__)
+   #include <mem.h> // for memset
+#endif 
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+
+// Refer to Document::SetMaxSizeLoadEntry()
+const unsigned int Document::MAX_SIZE_LOAD_ELEMENT_VALUE = 0xfff; // 4096
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+// Constructors and destructors are protected to avoid user to invoke directly
+
+/**
+ * \brief This default constructor neither loads nor parses the file. 
+ *        You should then invoke \ref Document::Load.
+ *         
+ */
+Document::Document() 
+         :ElementSet(-1)
+{
+   Fp = 0;
+
+   SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
+   Initialize();
+   SwapCode = 1234;
+   Filetype = ExplicitVR;
+   // Load will set it to true if sucessfull
+   Group0002Parsed = false;
+   IsDocumentAlreadyLoaded = false;
+   IsDocumentModified = true;
+   LoadMode = LD_ALL; // default : load everything, later
+   SetFileName("");
+}
+
+#ifndef GDCM_LEGACY_REMOVE
+/**
+ * \brief   Constructor (DEPRECATED : not to break the API) 
+ * @param   fileName 'Document' (File or DicomDir) to be open for parsing
+ */
+Document::Document( std::string const &fileName )
+         :ElementSet(-1) 
+{
+   Fp = 0;
+
+   SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
+   Initialize();
+   SwapCode = 1234;
+   Filetype = ExplicitVR;
+   Group0002Parsed = false;
+   LoadMode = LD_ALL; // Load everything, later
+
+   // Load will set it to true if sucessfull
+   IsDocumentAlreadyLoaded = false;
+   IsDocumentModified = true;
+
+   SetFileName(fileName);
+   Load( );
+}
+#endif
+/**
+ * \brief   Canonical destructor.
+ */
+Document::~Document ()
+{
+   CloseFile();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Loader. use SetLoadMode(), SetFileName() before ! 
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
+ */
+bool Document::Load(  ) 
+{
+   if ( GetFileName() == "" )
+   {
+      gdcmWarningMacro( "Use SetFileName, before !" );
+      return false;
+   }
+   return DoTheLoadingDocumentJob( );
+} 
+
+#ifndef GDCM_LEGACY_REMOVE
+/**
+ * \brief   Loader. (DEPRECATED : not to break the API)   
+ * @param   fileName 'Document' (File or DicomDir) to be open for parsing
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
+ */
+bool Document::Load( std::string const &fileName ) 
+{
+   Filename = fileName;
+   return DoTheLoadingDocumentJob( );
+}
+#endif
+
+/**
+ * \brief   Performs the Loading Job (internal use only)  
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
+ */
+bool Document::DoTheLoadingDocumentJob(  ) 
+{
+   if ( ! IsDocumentModified ) // Nothing to do !
+      return true;
+
+   ClearEntry();
+
+   Fp = 0;
+   if ( !OpenFile() )
+   {
+      // warning already performed in OpenFile()
+      Filetype = Unknown;
+      return false;
+   }
+
+   Group0002Parsed = false;
+
+   gdcmDebugMacro( "Starting parsing of file: " << Filename.c_str());
+
+   // Computes the total length of the file
+   Fp->seekg(0, std::ios::end);  // Once per Document !
+   long lgt = Fp->tellg();       // Once per Document !   
+   Fp->seekg(0, std::ios::beg);  // Once per Document !
+
+   // CheckSwap returns a boolean 
+   // (false if no swap info of any kind was found)
+   if (! CheckSwap() )
+   {
+      gdcmWarningMacro( "Neither a DICOM V3 nor an ACR-NEMA file: " 
+                   << Filename.c_str());
+      CloseFile(); 
+      return false;      
+    }
+
+   long beg = Fp->tellg();      // just after DICOM preamble (if any)
+
+   lgt -= beg;                  // remaining length to parse    
+
+   // Recursive call.
+   // Loading is done during parsing
+   ParseDES( this, beg, lgt, false); // delim_mode is first defaulted to false
+
+   if ( IsEmpty() )
+   { 
+      gdcmErrorMacro( "No tag in internal hash table for: "
+                        << Filename.c_str());
+      CloseFile(); 
+      return false;
+   }
+   IsDocumentAlreadyLoaded = true;
+
+   //Fp->seekg(0, std::ios::beg);  // Once per Document!
+   
+   // Load 'non string' values
+      
+   std::string PhotometricInterpretation = GetEntryValue(0x0028,0x0004);   
+   if ( PhotometricInterpretation == "PALETTE COLOR " )
+   {
+   // FIXME
+   // Probabely this line should be outside the 'if'
+   // Try to find an image sample holding a 'gray LUT'
+      LoadEntryBinArea(0x0028,0x1200);  // gray LUT
+   
+      /// FIXME
+      /// The tags refered by the three following lines used to be CORRECTLY
+      /// defined as having an US Value Representation in the public
+      /// dictionary. BUT the semantics implied by the three following
+      /// lines state that the corresponding tag contents are in fact
+      /// the ones of a BinEntry.
+      /// In order to fix things "Quick and Dirty" the dictionary was
+      /// altered on PURPOSE but now contains a WRONG value.
+      /// In order to fix things and restore the dictionary to its
+      /// correct value, one needs to decide of the semantics by deciding
+      /// whether the following tags are either :
+      /// - multivaluated US, and hence loaded as ValEntry, but afterwards
+      ///   also used as BinEntry, which requires the proper conversion,
+      /// - OW, and hence loaded as BinEntry, but afterwards also used
+      ///   as ValEntry, which requires the proper conversion.
+      // --> OB (byte aray) or OW (short int aray)
+      // The actual VR has to be deduced from other entries.
+      // Our way of loading them may fail in some cases :
+      // We must or not SwapByte depending on other field values.
+             
+      LoadEntryBinArea(0x0028,0x1201);  // R    LUT
+      LoadEntryBinArea(0x0028,0x1202);  // G    LUT
+      LoadEntryBinArea(0x0028,0x1203);  // B    LUT
+      
+      // Segmented Red   Palette Color LUT Data
+      LoadEntryBinArea(0x0028,0x1221);
+      // Segmented Green Palette Color LUT Data
+      LoadEntryBinArea(0x0028,0x1222);
+      // Segmented Blue  Palette Color LUT Data
+      LoadEntryBinArea(0x0028,0x1223);
+   }
+ 
+   //FIXME later : how to use it?
+   SeqEntry *modLutSeq = GetSeqEntry(0x0028,0x3000); // Modality LUT Sequence
+   if ( modLutSeq !=0 )
+   {
+      SQItem *sqi= modLutSeq->GetFirstSQItem();
+      if ( sqi != 0 )
+      {
+         BinEntry *b = sqi->GetBinEntry(0x0028,0x3006);
+         if ( b != 0 )
+         {
+            if ( b->GetLength() != 0 )
+            {
+               // FIXME : CTX dependent means : contexted dependant.
+               //         see upper comment.
+               LoadEntryBinArea(b);    //LUT Data (CTX dependent)
+            }   
+        }
+     }      
+   }
+
+   // Force Loading some more elements if user asked to.
+
+   gdcm::DocEntry *d;
+   for (ListElements::iterator it = UserForceLoadList.begin();  
+                               it != UserForceLoadList.end();
+                             ++it)
+   {
+      gdcmDebugMacro( "Force Load " << std::hex 
+                       << (*it).Group << "|" <<(*it).Elem );
+  
+      d = GetDocEntry( (*it).Group, (*it).Elem);
+  
+      if ( d == NULL)
+      {
+         gdcmWarningMacro( "You asked to ForceLoad "  << std::hex
+                          << (*it).Group <<"|"<< (*it).Elem
+                          << " that doesn't exist" );
+         continue;
+      }
+
+      if ( dynamic_cast<ValEntry *>(d) )
+      {
+         LoadDocEntry(d, true);
+         continue;
+      }
+
+      BinEntry *b = dynamic_cast<BinEntry *>(d);
+      if ( b )
+      {
+         LoadEntryBinArea(b);
+         b->SetValue(GDCM_BINLOADED);
+         continue;
+      }
+ 
+      if ( dynamic_cast<SeqEntry *>(d) )
+      {
+         gdcmWarningMacro( "You cannot 'ForceLoad' a SeqEntry :" << std::hex
+                           << (*it).Group <<"|"<< (*it).Elem );
+         continue;
+      }
+   }
+
+   CloseFile(); 
+  
+   // ----------------------------
+   // Specific code to allow gdcm to read ACR-LibIDO formated images
+   // Note: ACR-LibIDO is an extension of the ACR standard that was
+   //       used at CREATIS. For the time being (say a couple of years)
+   //       we keep this kludge to allow CREATIS users 
+   //       reading their old images.
+   //
+   // if recognition code tells us we deal with a LibIDO image
+   // we switch lineNumber and columnNumber
+   //
+   std::string RecCode;
+   RecCode = GetEntryValue(0x0008, 0x0010); // recognition code (RET)
+   if (RecCode == "ACRNEMA_LIBIDO_1.1" ||
+       RecCode == "CANRME_AILIBOD1_1." )  // for brain-damaged softwares
+                                          // with "little-endian strings"
+   {
+         Filetype = ACR_LIBIDO; 
+         std::string rows    = GetEntryValue(0x0028, 0x0010);
+         std::string columns = GetEntryValue(0x0028, 0x0011);
+         SetValEntry(columns, 0x0028, 0x0010);
+         SetValEntry(rows   , 0x0028, 0x0011);
+   }
+   // --- End of ACR-LibIDO kludge --- 
+   return true;
+}
+
+
+/**
+ * \brief Adds a new element we want to load anyway
+ * @param   group  Group number of the target tag.
+ * @param   elem Element number of the target tag.
+ */
+void Document::AddForceLoadElement (uint16_t group, uint16_t elem) 
+{ 
+   Element el;
+   el.Group = group;
+   el.Elem  = elem;
+   UserForceLoadList.push_back(el); 
+}
+/**
+ * \brief   Get the public dictionary used
+ */
+Dict *Document::GetPubDict()
+{
+   return RefPubDict;
+}
+
+/**
+ * \brief   Get the shadow dictionary used
+ */
+Dict *Document::GetShaDict()
+{
+   return RefShaDict;
+}
+
+/**
+ * \brief   Set the shadow dictionary used
+ * @param   dict dictionary to use in shadow
+ */
+bool Document::SetShaDict(Dict *dict)
+{
+   RefShaDict = dict;
+   return !RefShaDict;
+}
+
+/**
+ * \brief   Set the shadow dictionary used
+ * @param   dictName name of the dictionary to use in shadow
+ */
+bool Document::SetShaDict(DictKey const &dictName)
+{
+   RefShaDict = Global::GetDicts()->GetDict(dictName);
+   return !RefShaDict;
+}
+
+/**
+ * \brief  This predicate tells us whether or not the current Document 
+ *         was properly parsed and contains at least *one* Dicom Element
+ *         (and nothing more, sorry).
+ * @return false when we're 150 % sure it's NOT a Dicom/Acr file,
+ *         true otherwise. 
+ */
+bool Document::IsParsable()
+{
+   if ( Filetype == Unknown )
+   {
+      gdcmWarningMacro( "Wrong filetype for " << GetFileName());
+      return false;
+   }
+
+   if ( IsEmpty() )
+   { 
+      gdcmWarningMacro( "No tag in internal hash table.");
+      return false;
+   }
+
+   return true;
+}
+/**
+ * \brief  This predicate tells us whether or not the current Document 
+ *         was properly parsed and contains at least *one* Dicom Element
+ *         (and nothing more, sorry).
+ * @return false when we're 150 % sure it's NOT a Dicom/Acr file,
+ *         true otherwise. 
+ */
+bool Document::IsReadable()
+{
+   return IsParsable();
+}
+
+
+/**
+ * \brief   Predicate for dicom version 3 file.
+ * @return  True when the file is a dicom version 3.
+ */
+bool Document::IsDicomV3()
+{
+   // Checking if Transfer Syntax exists is enough
+   // Anyway, it's too late check if the 'Preamble' was found ...
+   // And ... would it be a rich idea to check ?
+   // (some 'no Preamble' DICOM images exist !)
+   return GetDocEntry(0x0002, 0x0010) != NULL;
+}
+
+/**
+ * \brief   Predicate for Papyrus file
+ *          Dedicated to whomsoever it may concern
+ * @return  True when the file is a Papyrus file.
+ */
+bool Document::IsPapyrus()
+{
+   // check for Papyrus private Sequence
+   DocEntry *e = GetDocEntry(0x0041, 0x1050);
+   if ( !e )
+      return false;
+   // check if it's actually a Sequence
+   if ( !dynamic_cast<SeqEntry*>(e) )
+      return  false;
+   return true;
+}
+
+/**
+ * \brief  returns the File Type 
+ *         (ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown)
+ * @return the FileType code
+ */
+FileType Document::GetFileType()
+{
+   return Filetype;
+}
+
+/**
+ * \brief   Accessor to the Transfer Syntax (when present) of the
+ *          current document (it internally handles reading the
+ *          value from disk when only parsing occured).
+ * @return  The encountered Transfer Syntax of the current document, if DICOM.
+ *          GDCM_UNKNOWN for ACR-NEMA files (or broken headers ...)
+ */
+std::string Document::GetTransferSyntax()
+{
+   DocEntry *entry = GetDocEntry(0x0002, 0x0010);
+   if ( !entry )
+   {
+      return GDCM_UNKNOWN;
+   }
+
+   // The entry might be present but not loaded (parsing and loading
+   // happen at different stages): try loading and proceed with check...
+   LoadDocEntrySafe(entry);
+   if (ValEntry *valEntry = dynamic_cast< ValEntry* >(entry) )
+   {
+      std::string transfer = valEntry->GetValue();
+      // The actual transfer (as read from disk) might be padded. We
+      // first need to remove the potential padding. We can make the
+      // weak assumption that padding was not executed with digits...
+      if  ( transfer.length() == 0 )
+      {
+         // for brain damaged headers
+         return GDCM_UNKNOWN;
+      }
+      while ( !isdigit((unsigned char)transfer[transfer.length()-1]) )
+      {
+         transfer.erase(transfer.length()-1, 1);
+         if  ( transfer.length() == 0 )
+         {
+            // for brain damaged headers
+            gdcmWarningMacro( "Transfer Syntax contains no valid character.");
+            return GDCM_UNKNOWN;
+         }
+      }
+      return transfer;
+   }
+   return GDCM_UNKNOWN;
+}
+
+/**
+ * \brief Accesses the info from 0002,0010 : Transfer Syntax and TS
+ * @return The full Transfer Syntax Name (as opposed to Transfer Syntax UID)
+ */
+std::string Document::GetTransferSyntaxName()
+{
+   // use the TS (TS : Transfer Syntax)
+   std::string transferSyntax = GetEntryValue(0x0002,0x0010);
+
+   if ( (transferSyntax.find(GDCM_NOTLOADED) < transferSyntax.length()) )
+   {
+      gdcmErrorMacro( "Transfer Syntax not loaded. " << std::endl
+               << "Better you increase MAX_SIZE_LOAD_ELEMENT_VALUE" );
+      return "Uncompressed ACR-NEMA";
+   }
+   if ( transferSyntax == GDCM_UNFOUND )
+   {
+      gdcmDebugMacro( "Unfound Transfer Syntax (0002,0010)");
+      return "Uncompressed ACR-NEMA";
+   }
+
+   // we do it only when we need it
+   const TSKey &tsName = Global::GetTS()->GetValue( transferSyntax );
+
+   // Global::GetTS() is a global static you shall never try to delete it!
+   return tsName;
+}
+//
+// --------------- Swap Code ------------------
+/**
+ * \brief   Swaps the bytes so they agree with the processor order
+ * @return  The properly swaped 16 bits integer.
+ */
+uint16_t Document::SwapShort(uint16_t a)
+{
+   if ( SwapCode == 4321 || SwapCode == 2143 )
+   {
+      //a = ((( a << 8 ) & 0xff00 ) | (( a >> 8 ) & 0x00ff ) );
+      // Save CPU time
+      a = ( a << 8 ) | ( a >> 8 );
+   }
+   return a;
+}
+
+/**
+ * \brief   Swaps back the bytes of 4-byte long integer accordingly to
+ *          processor order.
+ * @return  The properly swaped 32 bits integer.
+ */
+uint32_t Document::SwapLong(uint32_t a)
+{
+   switch (SwapCode)
+   {
+      case 1234 :
+         break;
+      case 4321 :
+//         a=( ((a<<24) & 0xff000000) | ((a<<8)  & 0x00ff0000) | 
+//             ((a>>8)  & 0x0000ff00) | ((a>>24) & 0x000000ff) );
+// save CPU time
+         a=( ( a<<24)               | ((a<<8)  & 0x00ff0000) | 
+             ((a>>8)  & 0x0000ff00) |  (a>>24)                );
+         break;   
+      case 3412 :
+//       a=( ((a<<16) & 0xffff0000) | ((a>>16) & 0x0000ffff) );
+         a=( (a<<16)                | (a>>16)  );
+         break;  
+      case 2143 :
+         a=( ((a<< 8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff)  );
+      break;
+      default :
+         gdcmErrorMacro( "Unexpected swap code:" << SwapCode );
+         a = 0;
+   }
+   return a;
+} 
+
+//
+// -----------------File I/O ---------------
+/**
+ * \brief  Tries to open the file \ref Document::Filename and
+ *         checks the preamble when existing.
+ * @return The FILE pointer on success. 
+ */
+std::ifstream *Document::OpenFile()
+{
+   HasDCMPreamble = false;
+   if (Filename.length() == 0) 
+   {
+      return 0;
+   }
+
+   if ( Fp )
+   {
+      gdcmDebugMacro( "File already open: " << Filename.c_str());
+      CloseFile();
+   }
+
+   Fp = new std::ifstream(Filename.c_str(), std::ios::in | std::ios::binary);
+   if ( ! *Fp )
+   {
+   // Don't user gdcmErrorMacro :
+   // a spurious message will appear when you use, for instance 
+   // gdcm::FileHelper *fh = new gdcm::FileHelper( outputFileName );
+   // to create outputFileName.
+   
+   // FIXME : if the upper comment is still usefull 
+   //         --> the constructor is not so good ...
+   
+      gdcmWarningMacro( "Cannot open file: " << Filename.c_str());
+      delete Fp;
+      Fp = 0;
+      return 0;
+      //exit(1); // No function is allowed to leave the application instead
+                 // of warning the caller
+   }
+ 
+   uint16_t zero = 0;
+   Fp->read((char*)&zero, (size_t)2);
+   if ( Fp->eof() )
+   {
+      CloseFile();
+      return 0;
+   }
+ 
+   //-- Broken ACR or DICOM with no Preamble; may start with a Shadow Group --
+   // FIXME : We cannot be sure the preable is only zeroes..
+   //         (see ACUSON-24-YBR_FULL-RLE.dcm )
+   if ( 
+       zero == 0x0001 || zero == 0x0100 || zero == 0x0002 || zero == 0x0200 ||
+       zero == 0x0003 || zero == 0x0300 || zero == 0x0004 || zero == 0x0400 ||
+       zero == 0x0005 || zero == 0x0500 || zero == 0x0006 || zero == 0x0600 ||
+       zero == 0x0007 || zero == 0x0700 || zero == 0x0008 || zero == 0x0800 )
+   {
+      std::string msg = Util::Format(
+        "ACR/DICOM starting by 0x(%04x) at the beginning of the file\n", zero);
+      // FIXME : is it a Warning message, or a Debug message?
+      gdcmWarningMacro( msg.c_str() );
+      return Fp;
+   }
+ 
+   //-- DICOM --
+   Fp->seekg(126L, std::ios::cur);  // Once per Document
+   char dicm[4]; // = {' ',' ',' ',' '};
+   Fp->read(dicm,  (size_t)4);
+   if ( Fp->eof() )
+   {
+      CloseFile();
+      return 0;
+   }
+   if ( memcmp(dicm, "DICM", 4) == 0 )
+   {
+      HasDCMPreamble = true;
+      return Fp;
+   }
+
+   // -- Neither ACR/No Preamble Dicom nor DICOMV3 file
+   CloseFile();
+   // Don't user Warning nor Error, not to pollute the output
+   // while directory recursive parsing ...
+   gdcmDebugMacro( "Neither ACR/No Preamble Dicom nor DICOMV3 file: "
+                      << Filename.c_str()); 
+   return 0;
+}
+
+/**
+ * \brief closes the file  
+ * @return  TRUE if the close was successfull 
+ */
+bool Document::CloseFile()
+{
+   if ( Fp )
+   {
+      Fp->close();
+      delete Fp;
+      Fp = 0;
+   }
+   return true;
+}
+
+/**
+ * \brief Writes in a file all the Entries (Dicom Elements) 
+ * @param fp file pointer on an already open file (actually: Output File Stream)
+ * @param filetype Type of the File to be written 
+ *          (ACR-NEMA, ExplicitVR, ImplicitVR)
+ */
+void Document::WriteContent(std::ofstream *fp, FileType filetype)
+{
+   // Skip if user wants to write an ACR-NEMA file
+
+   if ( filetype == ImplicitVR || filetype == ExplicitVR ||
+        filetype == JPEG )
+   {
+      // writing Dicom File Preamble
+      char filePreamble[128];
+      memset(filePreamble, 0, 128);
+      fp->write(filePreamble, 128);
+      fp->write("DICM", 4);
+   }
+
+   /*
+    * \todo rewrite later, if really usefull
+    *       - 'Group Length' element is optional in DICOM
+    *       - but un-updated odd groups lengthes can causes pb
+    *         (xmedcon breaker)
+    *
+    * if ( (filetype == ImplicitVR) || (filetype == ExplicitVR) )
+    *    UpdateGroupLength(false,filetype);
+    * if ( filetype == ACR)
+    *    UpdateGroupLength(true,ACR);
+    *
+    * --> Computing group length for groups with embeded Sequences
+    * --> was too much tricky / we were [in a hurry / too lazy]
+    * --> We don't write the element 0x0000 (group length)
+    */
+
+   ElementSet::WriteContent(fp, filetype); // This one is recursive
+}
+
+// -----------------------------------------
+// Content entries 
+/**
+ * \brief Loads (from disk) the element content 
+ *        when a string is not suitable
+ * @param group   group number of the Entry 
+ * @param elem  element number of the Entry
+ */
+void Document::LoadEntryBinArea(uint16_t group, uint16_t elem)
+{
+   // Search the corresponding DocEntry
+   DocEntry *docElement = GetDocEntry(group, elem);
+   if ( !docElement )
+   {
+      gdcmDebugMacro(std::hex << group << "|" << elem 
+                       <<  " doesn't exist" );
+      return;
+   }
+   BinEntry *binElement = dynamic_cast<BinEntry *>(docElement);
+   if ( !binElement )
+   {
+      gdcmWarningMacro(std::hex << group << "|" << elem 
+                       <<  "is NOT a BinEntry");
+      return;
+   }
+   LoadEntryBinArea(binElement);
+}
+
+/**
+ * \brief Loads (from disk) the element content 
+ *        when a string is not suitable
+ * @param elem  Entry whose binArea is going to be loaded
+ */
+void Document::LoadEntryBinArea(BinEntry *elem) 
+{
+   if (elem->GetBinArea() )
+      return;
+
+   bool openFile = !Fp;
+   if ( openFile )
+      OpenFile();
+
+   size_t o =(size_t)elem->GetOffset();
+   Fp->seekg(o, std::ios::beg);
+
+   size_t l = elem->GetLength();
+   uint8_t *a = new uint8_t[l];
+   if ( !a )
+   {
+      gdcmWarningMacro(  "Cannot allocate BinEntry content for : "
+                       << std::hex << elem->GetGroup() 
+                       << "|" << elem->GetElement() );
+      return;
+   }
+
+   // Read the data
+   Fp->read((char*)a, l);
+   if ( Fp->fail() || Fp->eof() )
+   {
+      delete[] a;
+      return;
+   }
+
+   elem->SetBinArea(a);
+
+   if ( openFile )
+      CloseFile();
+}
+
+/**
+ * \brief  Loads the element while preserving the current
+ *         underlying file position indicator as opposed to
+ *        LoadDocEntry that modifies it.
+ * @param entry   DocEntry whose value will be loaded. 
+ */
+void Document::LoadDocEntrySafe(DocEntry *entry)
+{
+   if ( Fp )
+   {
+      long PositionOnEntry = Fp->tellg();
+      LoadDocEntry(entry);
+      Fp->seekg(PositionOnEntry, std::ios::beg);
+   }
+}
+
+/**
+ * \brief   Compares two documents, according to \ref DicomDir rules
+ * \warning Does NOT work with ACR-NEMA files
+ * \todo    Find a trick to solve the pb (use RET fields ?)
+ * @param   document to compare with current one
+ * @return  true if 'smaller'
+ */
+bool Document::operator<(Document &document)
+{
+   // Patient Name
+   std::string s1 = GetEntryValue(0x0010,0x0010);
+   std::string s2 = document.GetEntryValue(0x0010,0x0010);
+   if (s1 < s2)
+   {
+      return true;
+   }
+   else if ( s1 > s2 )
+   {
+      return false;
+   }
+   else
+   {
+      // Patient ID
+      s1 = GetEntryValue(0x0010,0x0020);
+      s2 = document.GetEntryValue(0x0010,0x0020);
+      if ( s1 < s2 )
+      {
+         return true;
+      }
+      else if ( s1 > s2 )
+      {
+         return false;
+      }
+      else
+      {
+         // Study Instance UID
+         s1 = GetEntryValue(0x0020,0x000d);
+         s2 = document.GetEntryValue(0x0020,0x000d);
+         if ( s1 < s2 )
+         {
+            return true;
+         }
+         else if ( s1 > s2 )
+         {
+            return false;
+         }
+         else
+         {
+            // Serie Instance UID
+            s1 = GetEntryValue(0x0020,0x000e);
+            s2 = document.GetEntryValue(0x0020,0x000e);    
+            if ( s1 < s2 )
+            {
+               return true;
+            }
+            else if ( s1 > s2 )
+            {
+               return false;
+            }
+         }
+      }
+   }
+   return false;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+/**
+ * \brief Reads a supposed to be 16 Bits integer
+ *       (swaps it depending on processor endianness) 
+ * @return read value
+ */
+uint16_t Document::ReadInt16()
+   throw( FormatError )
+{
+   uint16_t g;
+   Fp->read ((char*)&g, (size_t)2);
+   if ( Fp->fail() )
+   {
+      throw FormatError( "Document::ReadInt16()", " file error." );
+   }
+   if ( Fp->eof() )
+   {
+      throw FormatError( "Document::ReadInt16()", "EOF." );
+   }
+   g = SwapShort(g); 
+   return g;
+}
+
+/**
+ * \brief  Reads a supposed to be 32 Bits integer
+ *        (swaps it depending on processor endianness)  
+ * @return read value
+ */
+uint32_t Document::ReadInt32()
+   throw( FormatError )
+{
+   uint32_t g;
+   Fp->read ((char*)&g, (size_t)4);
+   if ( Fp->fail() )
+   {
+      throw FormatError( "Document::ReadInt32()", " file error." );
+   }
+   if ( Fp->eof() )
+   {
+      throw FormatError( "Document::ReadInt32()", "EOF." );
+   }
+   g = SwapLong(g);
+   return g;
+}
+
+/**
+ * \brief skips bytes inside the source file 
+ * \warning NOT end user intended method !
+ * @return 
+ */
+void Document::SkipBytes(uint32_t nBytes)
+{
+   //FIXME don't dump the returned value
+   Fp->seekg((long)nBytes, std::ios::cur);
+}
+
+/**
+ * \brief   Re-computes the length of a ACR-NEMA/Dicom group from a DcmHeader
+ */
+int Document::ComputeGroup0002Length( /*FileType filetype*/ ) 
+{
+   uint16_t gr;
+   std::string vr;
+   
+   int groupLength = 0;
+   bool found0002 = false;   
+  
+   // for each zero-level Tag in the DCM Header
+   DocEntry *entry = GetFirstEntry();
+   while( entry )
+   {
+      gr = entry->GetGroup();
+
+      if ( gr == 0x0002 )
+      {
+         found0002 = true;
+
+         if ( entry->GetElement() != 0x0000 )
+         {
+            vr = entry->GetVR();
+
+            //if ( (vr == "OB")||(vr == "OW")||(vr == "UT")||(vr == "SQ"))
+            // (no SQ, OW, UT in group 0x0002;)
+               if ( vr == "OB" ) 
+               {
+                  // explicit VR AND (OB, OW, SQ, UT) : 4 more bytes
+                  groupLength +=  4;
+               }
+            groupLength += 2 + 2 + 4 + entry->GetLength();   
+         }
+      }
+      else if (found0002 )
+         break;
+
+      entry = GetNextEntry();
+   }
+   return groupLength; 
+}
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \brief Loads all the needed Dictionaries
+ * \warning NOT end user intended method !
+ */
+void Document::Initialize() 
+{
+   RefPubDict = Global::GetDicts()->GetDefaultPubDict();
+   RefShaDict = NULL;
+   Filetype   = Unknown;
+}
+
+/**
+ * \brief   Parses a DocEntrySet (Zero-level DocEntries or SQ Item DocEntries)
+ * @param set DocEntrySet we are going to parse ('zero level' or a SQItem)
+ * @param offset start of parsing
+ * @param l_max  length to parse (meaningless when we are in 'delimitor mode')
+ * @param delim_mode : whether we are in 'delimitor mode' (l=0xffffff) or not
+ */ 
+void Document::ParseDES(DocEntrySet *set, long offset, 
+                        long l_max, bool delim_mode)
+{
+   DocEntry *newDocEntry;
+   ValEntry *newValEntry;
+   BinEntry *newBinEntry;
+   SeqEntry *newSeqEntry;
+   VRKey vr;
+   bool used; // will be set to false when something wrong happens to an Entry.
+              // (Entry will then be deleted)
+   bool delim_mode_intern = delim_mode;
+   bool first = true;
+   gdcmDebugMacro( "Enter in ParseDES, delim-mode " <<  delim_mode
+                     << " at offset " << std::hex << "0x(" << offset << ")" ); 
+   while (true)
+   {
+      if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
+      {
+         break;
+      }
+
+      newDocEntry = ReadNextDocEntry( );
+
+      // FIXME :
+      // Private tag, in IMplicit VR are defaulted as a BinEntry,
+      // Very often they are only composed of Printable characters, 
+      // and could be defaulted as a ValEntry.
+      // It's too late to do the Job
+      // (we should check the value, but we know it after LoadDocEntry ...)
+      // --> in next gdcm major release let's unify ValEntry and BinEntry !
+
+      // Uncoment this printf line to be able to 'follow' the DocEntries
+      // when something *very* strange happens
+
+      if ( !newDocEntry )
+      {
+         break;
+      }
+
+       // an Item Starter found elsewhere but the first position
+       // of a SeqEntry means previous entry was a Sequence
+       // but we didn't get it (private Sequence + Implicit VR)
+       // we have to backtrack.
+      if ( !first && newDocEntry->IsItemStarter() )
+      {
+         // Debug message within the method !
+         newDocEntry = Backtrack(newDocEntry);
+      }
+      else
+      { 
+         PreviousDocEntry = newDocEntry; 
+      }
+ 
+      used = true;
+      newValEntry = dynamic_cast<ValEntry*>(newDocEntry);
+      newBinEntry = dynamic_cast<BinEntry*>(newDocEntry);
+
+      if ( newValEntry || newBinEntry )  
+      {
+       //////////////////////////// ContentEntry
+         if ( newBinEntry )
+         {
+            vr = newDocEntry->GetVR();
+            if ( Filetype == ExplicitVR && 
+                 !Global::GetVR()->IsVROfBinaryRepresentable(vr) )
+            { 
+                ////// Neither ValEntry NOR BinEntry: should mean UNKOWN VR
+                gdcmWarningMacro( std::hex << newDocEntry->GetGroup() 
+                                  << "|" << newDocEntry->GetElement()
+                                  << " : Neither Valentry, nor BinEntry." 
+                                  "Probably unknown VR.");
+            }
+
+         //////////////////// BinEntry or UNKOWN VR:
+
+            // When "this" is a Document the Key is simply of the
+            // form ( group, elem )...
+            //if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
+            //{
+            //   newBinEntry->SetKey( newBinEntry->GetKey() );
+            //}
+            // but when "this" is a SQItem, we are inserting this new
+            // valEntry in a sequence item, and the key has the
+            // generalized form (refer to \ref BaseTagKey):
+
+            // time waste hunting
+            //if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
+            //{
+            //   newBinEntry->SetKey(  parentSQItem->GetBaseTagKey()
+            //                       + newBinEntry->GetKey() );
+            //}
+           
+            if ( !set->AddEntry( newBinEntry ) )
+            {
+               gdcmWarningMacro( "in ParseDES : cannot add a BinEntry "
+                                   << newBinEntry->GetKey()  
+                                   << " (at offset : " 
+                                   << newBinEntry->GetOffset() << " )" );
+               used=false;
+            }
+            else
+            {
+               // Load only if we can add (not a duplicate key)
+               LoadDocEntry( newBinEntry );
+            }
+         }  // end BinEntry
+         else
+         {
+         /////////////////////// ValEntry
+
+            // When "set" is a Document, then we are at the top of the
+            // hierarchy and the Key is simply of the form ( group, elem )...
+            //if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
+            //{
+            //   newValEntry->SetKey( newValEntry->GetKey() );
+            //}
+            // ...but when "set" is a SQItem, we are inserting this new
+            // valEntry in a sequence item. Hence the key has the
+            // generalized form (refer to \ref BaseTagKey):
+
+            // time waste hunting
+            //if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
+            //{
+            //   newValEntry->SetKey(  parentSQItem->GetBaseTagKey()
+            //                      + newValEntry->GetKey() );
+            //}
+
+            if ( !set->AddEntry( newValEntry ) )
+            {
+              gdcmWarningMacro( "in ParseDES : cannot add a ValEntry "
+                                  << newValEntry->GetKey()
+                                  << " (at offset : " 
+                                  << newValEntry->GetOffset() << " )" );   
+              used=false;
+            }
+            else
+            {
+               // Load only if we can add (not a duplicate key)
+               LoadDocEntry( newValEntry );
+            }
+
+            if ( newValEntry->GetElement() == 0x0000 ) // if on group length
+            {
+               if ( newValEntry->GetGroup()%2 != 0 )   // if Shadow Group
+               {
+                  if ( LoadMode & LD_NOSHADOW ) // if user asked to skip shad.gr
+                  {
+                     std::string strLgrGroup = newValEntry->GetValue();
+                     int lgrGroup;
+                     if ( strLgrGroup != GDCM_UNFOUND)
+                     {
+                        lgrGroup = atoi(strLgrGroup.c_str());
+                        Fp->seekg(lgrGroup, std::ios::cur);
+                        //used = false;  // never used
+                        RemoveEntry( newDocEntry );  // Remove and delete
+                        // bcc 5.5 is right "assigned a value that's never used"
+                        // newDocEntry = 0;
+                        continue;
+                     }
+                  }
+               }
+            }
+
+            bool delimitor = newValEntry->IsItemDelimitor();
+
+            if ( (delimitor) || 
+                (!delim_mode && ((long)(Fp->tellg())-offset) >= l_max) )
+            {
+               if ( !used )
+                  delete newDocEntry;
+               break;
+            }
+         }
+
+         // Just to make sure we are at the beginning of next entry.
+         SkipToNextDocEntry(newDocEntry);
+      }
+      else
+      {
+         /////////////////////// SeqEntry :  VR = "SQ"
+
+         unsigned long l = newDocEntry->GetReadLength();          
+         if ( l != 0 ) // don't mess the delim_mode for 'zero-length sequence'
+         {
+            if ( l == 0xffffffff )
+            {
+              delim_mode_intern = true;
+            }
+            else
+            {
+              delim_mode_intern = false;
+            }
+         }
+
+         if ( (LoadMode & LD_NOSHADOWSEQ) && ! delim_mode_intern )
+         { 
+           // User asked to skip SeQuences *only* if they belong to Shadow Group
+            if ( newDocEntry->GetGroup()%2 != 0 )
+            {
+                Fp->seekg( l, std::ios::cur);
+                RemoveEntry( newDocEntry );  // Remove and delete
+                continue;  
+            } 
+         } 
+         if ( (LoadMode & LD_NOSEQ) && ! delim_mode_intern ) 
+         {
+           // User asked to skip *any* SeQuence
+            Fp->seekg( l, std::ios::cur);
+            RemoveEntry( newDocEntry );  // Remove and delete
+            continue;
+         }
+         // delay the dynamic cast as late as possible
+         newSeqEntry = dynamic_cast<SeqEntry*>(newDocEntry);
+         
+         // no other way to create the Delimitor ...
+         newSeqEntry->SetDelimitorMode( delim_mode_intern );
+
+         // At the top of the hierarchy, stands a Document. When "set"
+         // is a Document, then we are building the first depth level.
+         // Hence the SeqEntry we are building simply has a depth
+         // level of one:
+        if ( set == this ) // ( dynamic_cast< Document* > ( set ) )
+         {
+            newSeqEntry->SetDepthLevel( 1 );
+         }
+         // But when "set" is already a SQItem, we are building a nested
+         // sequence, and hence the depth level of the new SeqEntry
+         // we are building, is one level deeper:
+
+         // time waste hunting
+         else if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
+         {
+            newSeqEntry->SetDepthLevel( parentSQItem->GetDepthLevel() + 1 );
+         }
+
+         if ( l != 0 )
+         {  // Don't try to parse zero-length sequences
+
+            gdcmDebugMacro( "Entry in ParseSQ, delim " << delim_mode_intern
+                               << " at offset 0x(" << std::hex
+                               << newDocEntry->GetOffset() << ")");
+
+            ParseSQ( newSeqEntry, 
+                     newDocEntry->GetOffset(),
+                     l, delim_mode_intern);
+
+            gdcmDebugMacro( "Exit from ParseSQ, delim " << delim_mode_intern);
+ 
+         }
+         if ( !set->AddEntry( newSeqEntry ) )
+         {
+            gdcmWarningMacro( "in ParseDES : cannot add a SeqEntry "
+                                << newSeqEntry->GetKey()
+                                << " (at offset : 0x(" 
+                                << newSeqEntry->GetOffset() << ") )" ); 
+            used = false;
+         }
+ 
+         if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
+         {
+            if ( !used )
+               delete newDocEntry;  
+            break;
+         }
+      }  // end SeqEntry : VR = "SQ"
+
+      if ( !used )
+      {
+         delete newDocEntry;
+      }
+      first = false;
+   }                               // end While
+   gdcmDebugMacro( "Exit from ParseDES, delim-mode " << delim_mode );
+}
+
+/**
+ * \brief   Parses a Sequence ( SeqEntry after SeqEntry)
+ * @return  parsed length for this level
+ */ 
+void Document::ParseSQ( SeqEntry *seqEntry,
+                        long offset, long l_max, bool delim_mode)
+{
+   int SQItemNumber = 0;
+   bool dlm_mod;
+   long offsetStartCurrentSQItem = offset;
+
+   while (true)
+   {
+      // the first time, we read the fff0,e000 of the first SQItem
+      DocEntry *newDocEntry = ReadNextDocEntry();
+
+      if ( !newDocEntry )
+      {
+         gdcmWarningMacro("in ParseSQ : should never get here!");
+         break;
+      }
+      if ( delim_mode )
+      {
+         if ( newDocEntry->IsSequenceDelimitor() )
+         {
+            seqEntry->SetDelimitationItem( newDocEntry ); 
+            break;
+         }
+      }
+      if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
+      {
+         delete newDocEntry;
+         break;
+      }
+      // create the current SQItem
+      SQItem *itemSQ = new SQItem( seqEntry->GetDepthLevel() );
+      unsigned int l = newDocEntry->GetReadLength();
+      
+      if ( l == 0xffffffff )
+      {
+         dlm_mod = true;
+      }
+      else
+      {
+         dlm_mod = false;
+      }
+
+      // remove fff0,e000, created out of the SQItem
+      delete newDocEntry;
+      // fill up the current SQItem, starting at the beginning of fff0,e000
+
+      ParseDES(itemSQ, offsetStartCurrentSQItem, l+8, dlm_mod);
+
+      offsetStartCurrentSQItem = Fp->tellg();
+ 
+      seqEntry->AddSQItem( itemSQ, SQItemNumber ); 
+      SQItemNumber++;
+      if ( !delim_mode && ((long)(Fp->tellg())-offset ) >= l_max )
+      {
+         break;
+      }
+   }
+}
+
+/**
+ * \brief   When a private Sequence + Implicit VR is encountered
+ *           we cannot guess it's a Sequence till we find the first
+ *           Item Starter. We then backtrack to do the job.
+ * @param   docEntry Item Starter that warned us 
+ */
+DocEntry *Document::Backtrack(DocEntry *docEntry)
+{
+   // delete the Item Starter, built erroneously out of any Sequence
+   // it's not yet in the HTable/chained list
+   delete docEntry;
+
+   // Get all info we can from PreviousDocEntry
+   uint16_t group = PreviousDocEntry->GetGroup();
+   uint16_t elem  = PreviousDocEntry->GetElement();
+   uint32_t lgt   = PreviousDocEntry->GetLength();
+   long offset    = PreviousDocEntry->GetOffset();
+
+   gdcmDebugMacro( "Backtrack :" << std::hex << group 
+                                 << "|" << elem
+                                 << " at offset 0x(" <<offset << ")" );
+   RemoveEntry( PreviousDocEntry );
+
+   // forge the Seq Entry
+   DocEntry *newEntry = NewSeqEntry(group, elem);
+   newEntry->SetLength(lgt);
+   newEntry->SetOffset(offset);
+
+   // Move back to the beginning of the Sequence
+
+   Fp->seekg(offset, std::ios::beg); // Only for Shadow Implicit VR SQ
+   return newEntry;
+}
+
+/**
+ * \brief   Loads (or not) the element content depending if its length exceeds
+ *          or not the value specified with Document::SetMaxSizeLoadEntry()
+ * @param   entry Header Entry (Dicom Element) to be dealt with
+ * @param forceLoad whether you want to force loading of 'long' elements
+ */
+void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
+{
+   uint16_t group  = entry->GetGroup();
+   uint16_t elem   = entry->GetElement();
+   std::string  vr = entry->GetVR();
+   uint32_t length = entry->GetLength();
+
+   Fp->seekg((long)entry->GetOffset(), std::ios::beg);
+
+   // A SeQuence "contains" a set of Elements.  
+   //          (fffe e000) tells us an Element is beginning
+   //          (fffe e00d) tells us an Element just ended
+   //          (fffe e0dd) tells us the current SeQuence just ended
+   //          (fffe 0000) is an 'impossible' tag value, 
+   //                                    found in MR-PHILIPS-16-Multi-Seq.dcm
+   if ( (group == 0xfffe && elem != 0x0000 ) || vr == "SQ" )
+   {
+      // NO more value field for SQ !
+      return;
+   }
+
+   // When the length is zero things are easy:
+   if ( length == 0 )
+   {
+      ((ValEntry *)entry)->SetValue("");
+      return;
+   }
+
+   // The elements whose length is bigger than the specified upper bound
+   // are not loaded. Instead we leave a short notice on the offset of
+   // the element content and it's length.
+
+   itksys_ios::ostringstream s;
+
+   if (!forceLoad)
+   {
+      if (length > MaxSizeLoadEntry)
+      {
+         if (BinEntry *binEntryPtr = dynamic_cast< BinEntry* >(entry) )
+         {  
+            s << GDCM_NOTLOADED;
+            s << " Ad.:" << (long)entry->GetOffset();
+            s << " x(" << std::hex << entry->GetOffset() << ")";
+            s << std::dec;
+            s << " Lgt:"  << entry->GetLength();
+            s << " x(" << std::hex << entry->GetLength() << ")";
+            binEntryPtr->SetValue(s.str());
+         }
+         else if (ValEntry *valEntryPtr = dynamic_cast< ValEntry* >(entry) )
+         {
+            s << GDCM_NOTLOADED;  
+            s << " Address:" << (long)entry->GetOffset();
+            s << " Length:"  << entry->GetLength();
+            s << " x(" << std::hex << entry->GetLength() << ")";
+            valEntryPtr->SetValue(s.str());
+         }
+         else
+         {
+            // fusible
+            gdcmErrorMacro( "MaxSizeLoadEntry exceeded, neither a BinEntry "
+                         << "nor a ValEntry ?! Should never print that !" );
+         }
+
+       // to be sure we are at the end of the value ...
+       //  Fp->seekg((long)entry->GetOffset()+(long)entry->GetLength(),
+       //            std::ios::beg);
+       return;
+      }
+   }
+
+   // When we find a BinEntry not very much can be done :
+   if (BinEntry *binEntryPtr = dynamic_cast< BinEntry* >(entry) )
+   {
+      s << GDCM_BINLOADED;
+      binEntryPtr->SetValue(s.str());
+      LoadEntryBinArea(binEntryPtr); // last one, not to erase length !
+      return;
+   }
+
+   if ( IsDocEntryAnInteger(entry) )
+   {   
+      uint32_t NewInt;
+      int nbInt;
+      // When short integer(s) are expected, read and convert the following 
+      // (n * 2) characters properly i.e. consider them as short integers as
+      // opposed to strings.
+      // Elements with Value Multiplicity > 1
+      // contain a set of integers (not a single one)       
+      if (vr == "US" || vr == "SS")
+      {
+         nbInt = length / 2;
+         NewInt = ReadInt16();
+         s << NewInt;
+         if (nbInt > 1)
+         {
+            for (int i=1; i < nbInt; i++)
+            {
+               s << '\\';
+               NewInt = ReadInt16();
+               s << NewInt;
+            }
+         }
+      }
+      // See above comment on multiple integers (mutatis mutandis).
+      else if (vr == "UL" || vr == "SL")
+      {
+         nbInt = length / 4;
+         NewInt = ReadInt32();
+         s << NewInt;
+         if (nbInt > 1)
+         {
+            for (int i=1; i < nbInt; i++)
+            {
+               s << '\\';
+               NewInt = ReadInt32();
+               s << NewInt;
+            }
+         }
+      }
+#ifdef GDCM_NO_ANSI_STRING_STREAM
+      s << std::ends; // to avoid oddities on Solaris
+#endif //GDCM_NO_ANSI_STRING_STREAM
+
+      ((ValEntry *)entry)->SetValue(s.str());
+      return;
+   }
+   
+  // FIXME: We need an additional byte for storing \0 that is not on disk
+   char *str = new char[length+1];
+   Fp->read(str, (size_t)length);
+   str[length] = '\0'; //this is only useful when length is odd
+   // Special DicomString call to properly handle \0 and even length
+   std::string newValue;
+   if ( length % 2 )
+   {
+      newValue = Util::DicomString(str, length+1);
+      gdcmWarningMacro("Warning: bad length: " << length <<
+                       " For string :" <<  newValue.c_str()); 
+      // Since we change the length of string update it length
+      //entry->SetReadLength(length+1);
+   }
+   else
+   {
+      newValue = Util::DicomString(str, length);
+   }
+   delete[] str;
+
+   if ( ValEntry *valEntry = dynamic_cast<ValEntry* >(entry) )
+   {
+      if ( Fp->fail() || Fp->eof())
+      {
+         if ( Fp->fail() )
+            gdcmWarningMacro("--> fail");
+
+         gdcmWarningMacro("Unread element value " << valEntry->GetKey() 
+                          << " lgt : " << valEntry->GetReadLength() 
+                          << " at " << std::hex << valEntry->GetOffset());
+         valEntry->SetValue(GDCM_UNREAD);
+         return;
+      }
+
+//      if ( vr == "UI" )
+//      {
+//         // Because of correspondance with the VR dic
+//         valEntry->SetValue(newValue);
+//      }
+//      else
+//      {
+//         valEntry->SetValue(newValue);
+//      }
+
+// Anybody remembers the genesis of strange previous (commented out) code?
+      valEntry->SetValue(newValue);
+
+   }
+   else
+   {
+      gdcmWarningMacro("Should have a ValEntry, here ! " << valEntry->GetKey() 
+                          << " lgt : " << valEntry->GetReadLength() 
+                          << " at " << std::hex << valEntry->GetOffset());
+   }
+}
+
+/**
+ * \brief  Find the value Length of the passed Doc Entry
+ * @param  entry Header Entry whose length of the value shall be loaded. 
+ */
+void Document::FindDocEntryLength( DocEntry *entry )
+   throw ( FormatError )
+{
+   std::string vr  = entry->GetVR();
+   uint16_t length16;       
+   
+   if ( Filetype == ExplicitVR && !entry->IsImplicitVR() ) 
+   {
+      if ( vr == "OB" || vr == "OW" || vr == "SQ" || vr == "UT" 
+                                                           || vr == "UN" )
+      {
+         // The following reserved two bytes (see PS 3.5-2003, section
+         // "7.1.2 Data element structure with explicit vr", p 27) must be
+         // skipped before proceeding on reading the length on 4 bytes.
+
+         Fp->seekg( 2L, std::ios::cur); // Once per OW,OB,SQ DocEntry
+         uint32_t length32 = ReadInt32();
+
+         if ( (vr == "OB" || vr == "OW") && length32 == 0xffffffff ) 
+         {
+            uint32_t lengthOB;
+            try 
+            {
+               lengthOB = FindDocEntryLengthOBOrOW();// for encapsulation of encoded pixel 
+            }
+            catch ( FormatUnexpected )
+            {
+               // Computing the length failed (this happens with broken
+               // files like gdcm-JPEG-LossLess3a.dcm). We still have a
+               // chance to get the pixels by deciding the element goes
+               // until the end of the file. Hence we artificially fix the
+               // the length and proceed.
+               gdcmWarningMacro( " Computing the length failed for " << 
+                                   entry->GetKey() <<" in " <<GetFileName());
+
+               long currentPosition = Fp->tellg(); // Only for gdcm-JPEG-LossLess3a.dcm-like
+               Fp->seekg(0L,std::ios::end);        // Only for gdcm-JPEG-LossLess3a.dcm-like
+
+               long lengthUntilEOF = (long)(Fp->tellg())-currentPosition; // Only for gdcm-JPEG-LossLess3a.dcm-like
+               Fp->seekg(currentPosition, std::ios::beg);                 // Only for gdcm-JPEG-LossLess3a.dcm-like
+
+               entry->SetReadLength(lengthUntilEOF);
+               entry->SetLength(lengthUntilEOF);
+               return;
+            }
+            entry->SetReadLength(lengthOB);
+            entry->SetLength(lengthOB);
+            return;
+         }
+         FixDocEntryFoundLength(entry, length32); 
+         return;
+      }
+
+      // Length is encoded on 2 bytes.
+      length16 = ReadInt16();
+  
+      // 0xffff means that we deal with 'No Length' Sequence 
+      //        or 'No Length' SQItem
+      if ( length16 == 0xffff) 
+      {           
+         length16 = 0;
+      }
+      FixDocEntryFoundLength( entry, (uint32_t)length16 );
+      return;
+   }
+   else
+   {
+      // Either implicit VR or a non DICOM conformal (see note below) explicit
+      // VR that ommited the VR of (at least) this element. Farts happen.
+      // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25
+      // on Data elements "Implicit and Explicit VR Data Elements shall
+      // not coexist in a Data Set and Data Sets nested within it".]
+      // Length is on 4 bytes.
+
+     // Well ... group 0002 is always coded in 'Explicit VR Litle Endian'
+     // even if Transfer Syntax is 'Implicit VR ...'
+     // --> Except for 'Implicit VR Big Endian Transfer Syntax GE Private' 
+
+      FixDocEntryFoundLength( entry, ReadInt32() );
+      return;
+   }
+}
+
+/**
+ * \brief  Find the Length till the next sequence delimiter
+ * \warning NOT end user intended method !
+ * @return 
+ */
+uint32_t Document::FindDocEntryLengthOBOrOW()
+   throw( FormatUnexpected )
+{
+   // See PS 3.5-2001, section A.4 p. 49 on encapsulation of encoded pixel data.
+   long positionOnEntry = Fp->tellg(); // Only for OB,OW DataElements
+
+   bool foundSequenceDelimiter = false;
+   uint32_t totalLength = 0;
+
+   while ( !foundSequenceDelimiter )
+   {
+      uint16_t group;
+      uint16_t elem;
+      try
+      {
+         group = ReadInt16();
+         elem  = ReadInt16();   
+      }
+      catch ( FormatError )
+      {
+         throw FormatError("Unexpected end of file encountered during ",
+                           "Document::FindDocEntryLengthOBOrOW()");
+      }
+      // We have to decount the group and element we just read
+      totalLength += 4;     
+      if ( group != 0xfffe || ( ( elem != 0xe0dd ) && ( elem != 0xe000 ) ) )
+      {
+         gdcmWarningMacro( 
+              "Neither an Item tag nor a Sequence delimiter tag on :" 
+           << std::hex << group << " , " << elem 
+           << ")" );
+  
+         Fp->seekg(positionOnEntry, std::ios::beg); // Once per fragment (if any) of OB,OW DataElements
+         throw FormatUnexpected( 
+               "Neither an Item tag nor a Sequence delimiter tag.");
+      }
+      if ( elem == 0xe0dd )
+      {
+         foundSequenceDelimiter = true;
+      }
+      uint32_t itemLength = ReadInt32();
+      // We add 4 bytes since we just read the ItemLength with ReadInt32
+      totalLength += itemLength + 4;
+      SkipBytes(itemLength);
+      
+      if ( foundSequenceDelimiter )
+      {
+         break;
+      }
+   }
+   Fp->seekg( positionOnEntry, std::ios::beg); // Only for OB,OW DataElements
+   return totalLength;
+}
+
+/**
+ * \brief     Find the Value Representation of the current Dicom Element.
+ * @return    Value Representation of the current Entry
+ */
+std::string Document::FindDocEntryVR()
+{
+   if ( Filetype != ExplicitVR )
+      return GDCM_UNKNOWN;
+
+   long positionOnEntry = Fp->tellg();
+   // Warning: we believe this is explicit VR (Value Representation) because
+   // we used a heuristic that found "UL" in the first tag. Alas this
+   // doesn't guarantee that all the tags will be in explicit VR. In some
+   // cases (see e-film filtered files) one finds implicit VR tags mixed
+   // within an explicit VR file. Hence we make sure the present tag
+   // is in explicit VR and try to fix things if it happens not to be
+   // the case.
+
+   char vr[3];
+   Fp->read (vr, (size_t)2);
+   vr[2] = 0;
+
+   if ( !CheckDocEntryVR(vr) )
+   {
+      Fp->seekg(positionOnEntry, std::ios::beg);
+      return GDCM_UNKNOWN;
+   }
+   return vr;
+}
+
+/**
+ * \brief     Check the correspondance between the VR of the header entry
+ *            and the taken VR. If they are different, the header entry is 
+ *            updated with the new VR.
+ * @param     vr    Dicom Value Representation
+ * @return    false if the VR is incorrect or if the VR isn't referenced
+ *            otherwise, it returns true
+*/
+bool Document::CheckDocEntryVR(VRKey vr)
+{
+   if ( !Global::GetVR()->IsValidVR(vr) )
+      return false;
+
+   return true; 
+}
+
+/**
+ * \brief   Get the transformed value of the header entry. The VR value 
+ *          is used to define the transformation to operate on the value
+ * \warning NOT end user intended method !
+ * @param   entry entry to tranform
+ * @return  Transformed entry value
+ */
+std::string Document::GetDocEntryValue(DocEntry *entry)
+{
+   if ( IsDocEntryAnInteger(entry) && entry->IsImplicitVR() )
+   {
+      std::string val = ((ValEntry *)entry)->GetValue();
+      std::string vr  = entry->GetVR();
+      uint32_t length = entry->GetLength();
+      itksys_ios::ostringstream s;
+      int nbInt;
+
+      // When short integer(s) are expected, read and convert the following 
+      // n * 2 bytes properly i.e. as a multivaluated strings
+      // (each single value is separated fromthe next one by '\'
+      // as usual for standard multivaluated filels
+      // Elements with Value Multiplicity > 1
+      // contain a set of short integers (not a single one) 
+   
+      if ( vr == "US" || vr == "SS" )
+      {
+         uint16_t newInt16;
+
+         nbInt = length / 2;
+         for (int i=0; i < nbInt; i++) 
+         {
+            if ( i != 0 )
+            {
+               s << '\\';
+            }
+            newInt16 = ( val[2*i+0] & 0xFF ) + ( ( val[2*i+1] & 0xFF ) << 8);
+            newInt16 = SwapShort( newInt16 );
+            s << newInt16;
+         }
+      }
+
+      // When integer(s) are expected, read and convert the following 
+      // n * 4 bytes properly i.e. as a multivaluated strings
+      // (each single value is separated fromthe next one by '\'
+      // as usual for standard multivaluated filels
+      // Elements with Value Multiplicity > 1
+      // contain a set of integers (not a single one) 
+      else if ( vr == "UL" || vr == "SL" )
+      {
+         uint32_t newInt32;
+
+         nbInt = length / 4;
+         for (int i=0; i < nbInt; i++) 
+         {
+            if ( i != 0)
+            {
+               s << '\\';
+            }
+            newInt32 = ( val[4*i+0] & 0xFF )
+                    + (( val[4*i+1] & 0xFF ) <<  8 )
+                    + (( val[4*i+2] & 0xFF ) << 16 )
+                    + (( val[4*i+3] & 0xFF ) << 24 );
+            newInt32 = SwapLong( newInt32 );
+            s << newInt32;
+         }
+      }
+#ifdef GDCM_NO_ANSI_STRING_STREAM
+      s << std::ends; // to avoid oddities on Solaris
+#endif //GDCM_NO_ANSI_STRING_STREAM
+      return s.str();
+   }
+   return ((ValEntry *)entry)->GetValue();
+}
+
+/**
+ * \brief   Get the reverse transformed value of the header entry. The VR 
+ *          value is used to define the reverse transformation to operate on
+ *          the value
+ * \warning NOT end user intended method !
+ * @param   entry Entry to reverse transform
+ * @return  Reverse transformed entry value
+ */
+std::string Document::GetDocEntryUnvalue(DocEntry *entry)
+{
+   if ( IsDocEntryAnInteger(entry) && entry->IsImplicitVR() )
+   {
+      std::string vr = entry->GetVR();
+      std::vector<std::string> tokens;
+      itksys_ios::ostringstream s;
+
+      if ( vr == "US" || vr == "SS" ) 
+      {
+         uint16_t newInt16;
+
+         tokens.erase( tokens.begin(), tokens.end()); // clean any previous value
+         Util::Tokenize (((ValEntry *)entry)->GetValue(), tokens, "\\");
+         for (unsigned int i=0; i<tokens.size(); i++) 
+         {
+            newInt16 = atoi(tokens[i].c_str());
+            s << (  newInt16        & 0xFF ) 
+              << (( newInt16 >> 8 ) & 0xFF );
+         }
+         tokens.clear();
+      }
+      if ( vr == "UL" || vr == "SL")
+      {
+         uint32_t newInt32;
+
+         tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
+         Util::Tokenize (((ValEntry *)entry)->GetValue(), tokens, "\\");
+         for (unsigned int i=0; i<tokens.size();i++) 
+         {
+            newInt32 = atoi(tokens[i].c_str());
+            s << (char)(  newInt32         & 0xFF ) 
+              << (char)(( newInt32 >>  8 ) & 0xFF )
+              << (char)(( newInt32 >> 16 ) & 0xFF )
+              << (char)(( newInt32 >> 24 ) & 0xFF );
+         }
+         tokens.clear();
+      }
+
+#ifdef GDCM_NO_ANSI_STRING_STREAM
+      s << std::ends; // to avoid oddities on Solaris
+#endif //GDCM_NO_ANSI_STRING_STREAM
+      return s.str();
+   }
+
+   return ((ValEntry *)entry)->GetValue();
+}
+
+/**
+ * \brief   Skip a given Header Entry 
+ * \warning NOT end user intended method !
+ * @param   entry entry to skip
+ */
+void Document::SkipDocEntry(DocEntry *entry) 
+{
+   SkipBytes(entry->GetLength());
+}
+
+/**
+ * \brief   Skips to the beginning of the next Header Entry 
+ * \warning NOT end user intended method !
+ * @param   currentDocEntry entry to skip
+ */
+void Document::SkipToNextDocEntry(DocEntry *currentDocEntry) 
+{
+   long l = currentDocEntry->GetReadLength();
+   if ( l == -1 ) // length = 0xffff shouldn't appear here ...
+                  // ... but PMS imagers happen !
+      return;
+   Fp->seekg((size_t)(currentDocEntry->GetOffset()), std::ios::beg); //FIXME :each DocEntry
+   if (currentDocEntry->GetGroup() != 0xfffe)  // for fffe pb
+   {
+      Fp->seekg( l,std::ios::cur);                                 //FIXME :each DocEntry
+   }
+}
+
+/**
+ * \brief   When the length of an element value is obviously wrong (because
+ *          the parser went Jabberwocky) one can hope improving things by
+ *          applying some heuristics.
+ * @param   entry entry to check
+ * @param   foundLength first assumption about length    
+ */
+void Document::FixDocEntryFoundLength(DocEntry *entry,
+                                      uint32_t foundLength)
+{
+   entry->SetReadLength( foundLength );// will be updated only if a bug is found
+   if ( foundLength == 0xffffffff)
+   {
+      foundLength = 0;
+   }
+   
+   uint16_t gr   = entry->GetGroup();
+   uint16_t elem = entry->GetElement(); 
+     
+   if ( foundLength % 2)
+   {
+      gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength
+        <<  " in x(" << std::hex << gr << "," << elem <<")");
+   }
+      
+   //////// Fix for some naughty General Electric images.
+   // Allthough not recent many such GE corrupted images are still present
+   // on Creatis hard disks. Hence this fix shall remain when such images
+   // are no longer in use (we are talking a few years, here)...
+   // Note: XMedCon probably uses such a trick since it is able to read
+   //       those pesky GE images ...
+   if ( foundLength == 13)
+   {
+      // Only happens for this length !
+      if ( gr != 0x0008 || ( elem != 0x0070 && elem != 0x0080 ) )
+      {
+         foundLength = 10;
+         entry->SetReadLength(10); // a bug is to be fixed !?
+      }
+   }
+
+   //////// Fix for some brain-dead 'Leonardo' Siemens images.
+   // Occurence of such images is quite low (unless one leaves close to a
+   // 'Leonardo' source. Hence, one might consider commenting out the
+   // following fix on efficiency reasons.
+   else if ( gr   == 0x0009 && ( elem == 0x1113 || elem == 0x1114 ) )
+   {
+      foundLength = 4;
+      entry->SetReadLength(4); // a bug is to be fixed !
+   } 
+ 
+   else if ( entry->GetVR() == "SQ" )
+   {
+      foundLength = 0;      // ReadLength is unchanged 
+   } 
+    
+   //////// We encountered a 'delimiter' element i.e. a tag of the form 
+   // "fffe|xxxx" which is just a marker. Delimiters length should not be
+   // taken into account.
+   else if ( gr == 0xfffe )
+   {    
+     // According to the norm, fffe|0000 shouldn't exist. BUT the Philips
+     // image gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm happens to
+     // causes extra troubles...
+     if ( entry->GetElement() != 0x0000 )
+     {
+        foundLength = 0;
+     }
+   }
+   entry->SetLength(foundLength);
+}
+
+/**
+ * \brief   Apply some heuristics to predict whether the considered 
+ *          element value contains/represents an integer or not.
+ * @param   entry The element value on which to apply the predicate.
+ * @return  The result of the heuristical predicate.
+ */
+bool Document::IsDocEntryAnInteger(DocEntry *entry)
+{
+   uint16_t elem         = entry->GetElement();
+   uint16_t group        = entry->GetGroup();
+   const std::string &vr = entry->GetVR();
+   uint32_t length       = entry->GetLength();
+
+   // When we have some semantics on the element we just read, and if we
+   // a priori know we are dealing with an integer, then we shall be
+   // able to swap it's element value properly.
+   if ( elem == 0 )  // This is the group length of the group
+   {  
+      if ( length == 4 )
+      {
+         return true;
+      }
+      else 
+      {
+         // Although this should never happen, still some images have a
+         // corrupted group length [e.g. have a glance at offset x(8336) of
+         // gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm.
+         // Since for dicom compliant and well behaved headers, the present
+         // test is useless (and might even look a bit paranoid), when we
+         // encounter such an ill-formed image, we simply display a warning
+         // message and proceed on parsing (while crossing fingers).
+         long filePosition = Fp->tellg(); // Only when elem 0x0000 length is not 4 (?!?)
+         gdcmWarningMacro( "Erroneous Group Length element length  on : (" 
+           << std::hex << group << " , " << elem
+           << ") -before- position x(" << filePosition << ")"
+           << "lgt : " << length );
+      }
+   }
+
+   if ( vr == "UL" || vr == "US" || vr == "SL" || vr == "SS" )
+   {
+      return true;
+   }   
+   return false;
+}
+
+/**
+ * \brief   Discover what the swap code is (among little endian, big endian,
+ *          bad little endian, bad big endian).
+ *          sw is set
+ * @return false when we are absolutely sure 
+ *               it's neither ACR-NEMA nor DICOM
+ *         true  when we hope ours assuptions are OK
+ */
+bool Document::CheckSwap()
+{   
+   uint32_t  s32;
+   uint16_t  s16;
+       
+   char deb[256];
+    
+   // First, compare HostByteOrder and NetworkByteOrder in order to
+   // determine if we shall need to swap bytes (i.e. the Endian type).
+   bool net2host = Util::IsCurrentProcessorBigEndian();
+         
+   // The easiest case is the one of a 'true' DICOM header, we just have
+   // to look for the string "DICM" inside the file preamble.
+   Fp->read(deb, 256);
+   
+   char *entCur = deb + 128;
+   if ( memcmp(entCur, "DICM", (size_t)4) == 0 )
+   {
+      gdcmDebugMacro( "Looks like DICOM Version3 (preamble + DCM)" );
+      
+      // Group 0002 should always be VR, and the first element 0000
+      // Let's be carefull (so many wrong headers ...)
+      // and determine the value representation (VR) : 
+      // Let's skip to the first element (0002,0000) and check there if we find
+      // "UL"  - or "OB" if the 1st one is (0002,0001) -,
+      // in which case we (almost) know it is explicit VR.
+      // WARNING: if it happens to be implicit VR then what we will read
+      // is the length of the group. If this ascii representation of this
+      // length happens to be "UL" then we shall believe it is explicit VR.
+      // We need to skip :
+      // * the 128 bytes of File Preamble (often padded with zeroes),
+      // * the 4 bytes of "DICM" string,
+      // * the 4 bytes of the first tag (0002, 0000),or (0002, 0001)
+      // i.e. a total of  136 bytes.
+      entCur = deb + 136;
+     
+      // group 0x0002 *is always* Explicit VR Sometimes ,
+      // even if elem 0002,0010 (Transfer Syntax) tells us the file is
+      // *Implicit* VR  (see former 'gdcmData/icone.dcm')
+      
+      if ( memcmp(entCur, "UL", (size_t)2) == 0 ||
+           memcmp(entCur, "OB", (size_t)2) == 0 ||
+           memcmp(entCur, "UI", (size_t)2) == 0 ||
+           memcmp(entCur, "CS", (size_t)2) == 0 )  // CS, to remove later
+                                                   // when Write DCM *adds*
+      // FIXME
+      // Use Document::dicom_vr to test all the possibilities
+      // instead of just checking for UL, OB and UI !? group 0000 
+      {
+         Filetype = ExplicitVR;
+         gdcmDebugMacro( "Group 0002 : Explicit Value Representation");
+      } 
+      else 
+      {
+         Filetype = ImplicitVR;
+         gdcmWarningMacro( "Group 0002 :Not an explicit Value Representation;"
+                        << "Looks like a bugged Header!");
+      }
+      
+      if ( net2host )
+      {
+         SwapCode = 4321;
+         gdcmDebugMacro( "HostByteOrder != NetworkByteOrder, SwapCode = 4321");
+      }
+      else 
+      {
+         SwapCode = 1234;
+         gdcmDebugMacro( "HostByteOrder = NetworkByteOrder, SwapCode = 1234");
+      }
+      
+      // Position the file position indicator at first tag 
+      // (i.e. after the file preamble and the "DICM" string).
+
+      Fp->seekg ( 132L, std::ios::beg); // Once per Document
+      return true;
+   } // ------------------------------- End of DicomV3 ----------------
+
+   // Alas, this is not a DicomV3 file and whatever happens there is no file
+   // preamble. We can reset the file position indicator to where the data
+   // is (i.e. the beginning of the file).
+
+   gdcmWarningMacro( "Not a Kosher DICOM Version3 file (no preamble)");
+
+   Fp->seekg(0, std::ios::beg); // Once per ACR-NEMA Document
+
+   // Let's check 'No Preamble Dicom File' :
+   // Should start with group 0x0002
+   // and be Explicit Value Representation
+
+   s16 = *((uint16_t *)(deb));
+   SwapCode = 0;     
+   switch ( s16 )
+   {
+      case 0x0002 :
+         SwapCode = 1234;
+         entCur = deb + 4;
+         break;
+      case 0x0200 :
+         SwapCode = 4321;
+         entCur = deb + 6;
+    } 
+
+   if ( SwapCode != 0 )
+   {
+      if ( memcmp(entCur, "UL", (size_t)2) == 0 ||
+           memcmp(entCur, "OB", (size_t)2) == 0 ||
+           memcmp(entCur, "UI", (size_t)2) == 0 ||
+           memcmp(entCur, "SH", (size_t)2) == 0 ||
+           memcmp(entCur, "AE", (size_t)2) == 0 ||
+           memcmp(entCur, "OB", (size_t)2) == 0 )
+         {
+            Filetype = ExplicitVR;  // FIXME : not enough to say it's Explicit
+                                    // Wait untill reading Transfer Syntax
+            gdcmDebugMacro( "Group 0002 : Explicit Value Representation");
+            return true;
+          }
+    }
+// ------------------------------- End of 'No Preamble' DicomV3 -------------
+
+   // Our next best chance would be to be considering a 'clean' ACR/NEMA file.
+   // By clean we mean that the length of the first group is written down.
+   // If this is the case and since the length of the first group HAS to be
+   // four (bytes), then determining the proper swap code is straightforward.
+
+   entCur = deb + 4;
+   // We assume the array of char we are considering contains the binary
+   // representation of a 32 bits integer. Hence the following dirty
+   // trick :
+   s32 = *((uint32_t *)(entCur));
+   switch( s32 )
+   {
+      case 0x00040000 :
+         SwapCode = 3412;
+         Filetype = ACR;
+         return true;
+      case 0x04000000 :
+         SwapCode = 4321;
+         Filetype = ACR;
+         return true;
+      case 0x00000400 :
+         SwapCode = 2143;
+         Filetype = ACR;
+         return true;
+      case 0x00000004 :
+         SwapCode = 1234;
+         Filetype = ACR;
+         return true;
+      default :
+         // We are out of luck. It is not a DicomV3 nor a 'clean' ACR/NEMA file.
+         // It is time for despaired wild guesses. 
+         // So, let's check if this file wouldn't happen to be 'dirty' ACR/NEMA,
+         //  i.e. the 'group length' element is not present :     
+         
+         //  check the supposed-to-be 'group number'
+         //  in ( 0x0001 .. 0x0008 )
+         //  to determine ' SwapCode' value .
+         //  Only 0 or 4321 will be possible 
+         //  (no oportunity to check for the formerly well known
+         //  ACR-NEMA 'Bad Big Endian' or 'Bad Little Endian' 
+         //  if unsuccessfull (i.e. neither 0x0002 nor 0x0200 etc-3, 4, ..., 8-)
+         //  the file IS NOT ACR-NEMA nor DICOM V3
+         //  Find a trick to tell it the caller...
+      
+         s16 = *((uint16_t *)(deb));
+      
+         switch ( s16 )
+         {
+            case 0x0001 :
+            case 0x0002 :
+            case 0x0003 :
+            case 0x0004 :
+            case 0x0005 :
+            case 0x0006 :
+            case 0x0007 :
+            case 0x0008 :
+               SwapCode = 1234;
+               Filetype = ACR;
+               return true;
+            case 0x0100 :
+            case 0x0200 :
+            case 0x0300 :
+            case 0x0400 :
+            case 0x0500 :
+            case 0x0600 :
+            case 0x0700 :
+            case 0x0800 :
+               SwapCode = 4321;
+               Filetype = ACR;
+               return true;
+            default :
+               gdcmWarningMacro("ACR/NEMA unfound swap info (Hopeless !)");
+               Filetype = Unknown;
+               return false;
+         }
+   }
+}
+
+/**
+ * \brief Change the Byte Swap code. 
+ */
+void Document::SwitchByteSwapCode() 
+{
+   gdcmDebugMacro( "Switching Byte Swap code from "<< SwapCode
+                     << " at: 0x" << std::hex << Fp->tellg() );  // Only when DEBUG
+   if ( SwapCode == 1234 ) 
+   {
+      SwapCode = 4321;
+   }
+   else if ( SwapCode == 4321 ) 
+   {
+      SwapCode = 1234;
+   }
+   else if ( SwapCode == 3412 ) 
+   {
+      SwapCode = 2143;
+   }
+   else if ( SwapCode == 2143 )
+   {
+      SwapCode = 3412;
+   }
+   gdcmDebugMacro( " Into: "<< SwapCode );
+}
+
+/**
+ * \brief  during parsing, Header Elements too long are not loaded in memory
+ * @param newSize new size
+ */
+void Document::SetMaxSizeLoadEntry(long newSize) 
+{
+   if ( newSize < 0 )
+   {
+      return;
+   }
+   if ((uint32_t)newSize >= (uint32_t)0xffffffff )
+   {
+      MaxSizeLoadEntry = 0xffffffff;
+      return;
+   }
+   MaxSizeLoadEntry = newSize;
+   IsDocumentModified = true;
+}
+
+/**
+ * \brief   Read the next tag WITHOUT loading it's value
+ *          (read the 'Group Number', the 'Element Number',
+ *          gets the Dict Entry
+ *          gets the VR, gets the length, gets the offset value)
+ * @return  On succes : the newly created DocEntry, NULL on failure.      
+ */
+DocEntry *Document::ReadNextDocEntry()
+{
+   uint16_t group;
+   uint16_t elem;
+
+   try
+   {
+      group = ReadInt16();
+      elem  = ReadInt16();
+   }
+   catch ( FormatError )
+   {
+      // We reached the EOF (or an error occured) therefore 
+      // header parsing has to be considered as finished.
+      return 0;
+   }
+
+   // Sometimes file contains groups of tags with reversed endianess.
+   HandleBrokenEndian(group, elem);
+
+   // In 'true DICOM' files Group 0002 is always little endian
+   if ( HasDCMPreamble )
+      HandleOutOfGroup0002(group, elem);
+ 
+   std::string vr = FindDocEntryVR();
+   std::string realVR = vr;
+
+   if ( vr == GDCM_UNKNOWN )
+   {
+      if ( elem == 0x0000 ) // Group Length
+      {
+         realVR = "UL";     // must be UL
+      }
+      else if (group%2 == 1 &&  (elem >= 0x0010 && elem <=0x00ff ))
+      {  
+      // DICOM PS 3-5 7.8.1 a) states that those 
+      // (gggg-0010->00FF where gggg is odd) attributes have to be LO
+         realVR = "LO";
+      }
+      else
+      {
+         DictEntry *dictEntry = GetDictEntry(group,elem);
+         if ( dictEntry )
+         {
+            realVR = dictEntry->GetVR();
+         }
+      }
+   }
+
+   DocEntry *newEntry;
+   if ( Global::GetVR()->IsVROfSequence(realVR) )
+      newEntry = NewSeqEntry(group, elem);
+   else if ( Global::GetVR()->IsVROfStringRepresentable(realVR) )
+      newEntry = NewValEntry(group, elem, realVR);
+   else
+      newEntry = NewBinEntry(group, elem, realVR);
+
+   if ( vr == GDCM_UNKNOWN )
+   {
+      if ( Filetype == ExplicitVR )
+      {
+         // We thought this was explicit VR, but we end up with an
+         // implicit VR tag. Let's backtrack.
+         if ( newEntry->GetGroup() != 0xfffe )
+         { 
+            std::string msg;
+            int offset = Fp->tellg();
+            msg = Util::Format("Entry (%04x,%04x) at 0x(%x) should be Explicit VR\n", 
+                          newEntry->GetGroup(), newEntry->GetElement(), offset );
+            gdcmWarningMacro( msg.c_str() );
+          }
+      }
+      newEntry->SetImplicitVR();
+   }
+
+   try
+   {
+      FindDocEntryLength(newEntry);
+   }
+   catch ( FormatError )
+   {
+      // Call it quits
+      delete newEntry;
+      return 0;
+   }
+
+   newEntry->SetOffset(Fp->tellg());  // for each DocEntry
+
+   return newEntry;
+}
+
+/**
+ * \brief   Handle broken private tag from Philips NTSCAN
+ *          where the endianess is being switched to BigEndian 
+ *          for no apparent reason
+ * @return  no return
+ */
+void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
+{
+   // Endian reversion. 
+   // Some files contain groups of tags with reversed endianess.
+   static int reversedEndian = 0;
+   // try to fix endian switching in the middle of headers
+   if ((group == 0xfeff) && (elem == 0x00e0))
+   {
+     // start endian swap mark for group found
+     gdcmDebugMacro( "Start endian swap mark found." );
+     reversedEndian++;
+     SwitchByteSwapCode();
+     // fix the tag
+     group = 0xfffe;
+     elem  = 0xe000;
+   } 
+   else if (group == 0xfffe && elem == 0xe00d && reversedEndian) 
+   {
+     // end of reversed endian group
+     gdcmDebugMacro( "End of reversed endian." );
+     reversedEndian--;
+     SwitchByteSwapCode();
+   }
+   else if (group == 0xfeff && elem == 0xdde0) 
+   {
+     // reversed Sequence Terminator found
+     // probabely a bug in the header !
+     // Do what you want, it breaks !
+     //reversedEndian--;
+     //SwitchByteSwapCode();
+     gdcmWarningMacro( "Should never get here! reversed Sequence Terminator!" );
+     // fix the tag
+      group = 0xfffe;
+      elem  = 0xe0dd;  
+   }
+   else if (group == 0xfffe && elem == 0xe0dd) 
+   {
+      gdcmDebugMacro( "Straight Sequence Terminator." );  
+   }
+}
+
+/**
+ * \brief   Group 0002 is always coded Little Endian
+ *          whatever Transfer Syntax is
+ * @return  no return
+ */
+void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
+{
+   // Endian reversion. 
+   // Some files contain groups of tags with reversed endianess.
+   if ( !Group0002Parsed && group != 0x0002)
+   {
+      Group0002Parsed = true;
+      // we just came out of group 0002
+      // if Transfer Syntax is Big Endian we have to change CheckSwap
+
+      std::string ts = GetTransferSyntax();
+      if ( !Global::GetTS()->IsTransferSyntax(ts) )
+      {
+         gdcmWarningMacro("True DICOM File, with NO Tansfer Syntax: " << ts );
+         return;
+      }
+
+      // Group 0002 is always 'Explicit ...' 
+      // even when Transfer Syntax says 'Implicit ..." 
+
+      if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian )
+         {
+            Filetype = ImplicitVR;
+         }
+       
+      // FIXME Strangely, this works with 
+      //'Implicit VR BigEndian Transfer Syntax' (GE Private)
+      //
+      // --> Probabely normal, since we considered we never have 
+      // to trust manufacturers.
+      // (we find very often 'Implicit VR' tag, 
+      // even when Transfer Syntax tells us it's Explicit ...
+      if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian )
+      {
+         gdcmDebugMacro("Transfer Syntax Name = [" 
+                        << GetTransferSyntaxName() << "]" );
+         SwitchByteSwapCode();
+         group = SwapShort(group);
+         elem  = SwapShort(elem);
+      }
+   }
+}
+
+//-----------------------------------------------------------------------------
+// Print
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmDocument.h b/Utilities/ITK/Utilities/gdcm/src/gdcmDocument.h
new file mode 100644
index 0000000000000000000000000000000000000000..312657504edbcebd2db16230cf91be78b10b8ed1
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmDocument.h
@@ -0,0 +1,245 @@
+/*=========================================================================
+ 
+  Program:   gdcm
+  Module:    $RCSfile: gdcmDocument.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.9 $
+ 
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+ 
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+ 
+=========================================================================*/
+
+#ifndef GDCMDOCUMENT_H
+#define GDCMDOCUMENT_H
+
+#include "gdcmVR.h"
+#include "gdcmDict.h"
+#include "gdcmElementSet.h"
+#include "gdcmException.h"
+#include "gdcmDebug.h"
+
+#include <map>
+#include <list>
+#include <fstream>
+
+namespace gdcm 
+{
+class ValEntry;
+class BinEntry;
+class SeqEntry;
+class Dict;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief Derived by both gdcm::File and gdcm::DicomDir
+ */
+class GDCM_EXPORT Document : public ElementSet
+{
+public:
+
+typedef std::list<Element> ListElements;
+
+// Loading
+   //Deprecated : use SetFileName() + Load()
+#ifndef GDCM_LEGACY_REMOVE 
+   virtual bool Load( std::string const &filename ); 
+#endif
+   virtual bool Load( ); 
+
+// Dictionaries
+   Dict *GetPubDict();
+   Dict *GetShaDict();
+   bool SetShaDict(Dict *dict);
+   bool SetShaDict(DictKey const &dictName);
+
+// Informations contained in the gdcm::Document
+   bool IsParsable();
+   virtual bool IsReadable();
+   bool IsDicomV3();
+   bool IsPapyrus();
+   FileType GetFileType();
+   std::string GetTransferSyntax();
+   /// Return the Transfer Syntax as a string
+   std::string GetTransferSyntaxName();
+
+// Swap code
+   /// 'Swap code' accessor (see \ref SwapCode )
+   int GetSwapCode() { return SwapCode; }
+   // System access (meaning endian related !?)
+   uint16_t SwapShort(uint16_t);
+   uint32_t SwapLong(uint32_t);
+   /// \brief  Unswaps back the bytes of 2-bytes long integer 
+   ///         so they agree with the processor order.
+   uint16_t UnswapShort(uint16_t a) { return SwapShort(a);}
+   /// \brief  Unswaps back the bytes of 4-byte long integer 
+   ///         so they agree with the processor order.
+   uint32_t UnswapLong(uint32_t a) { return SwapLong(a);}
+   
+// File I/O
+   /// Accessor to \ref Filename
+   const std::string &GetFileName() const { return Filename; }
+   /// Accessor to \ref Filename
+   virtual void SetFileName(std::string const &fileName) 
+                   { if (Filename != fileName)
+                        Filename = fileName, IsDocumentModified = true; }
+
+   std::ifstream *OpenFile();
+   bool CloseFile();
+   void WriteContent( std::ofstream *fp, FileType type );
+
+// Content entries
+   virtual void LoadEntryBinArea(uint16_t group, uint16_t elem);
+   virtual void LoadEntryBinArea(BinEntry *entry);
+
+   void LoadDocEntrySafe(DocEntry *entry);
+   void SetMaxSizeLoadEntry(long);
+   void AddForceLoadElement(uint16_t group, uint16_t elem);
+ 
+// Ordering of Documents
+   bool operator<(Document &document);
+
+/**
+ * \brief Sets the LoadMode as a boolean string. 
+ *        LD_NOSEQ, LD_NOSHADOW, LD_NOSHADOWSEQ
+ ... (nothing more, right now)
+ *        WARNING : before using NO_SHADOW, be sure *all* your files
+ *        contain accurate values in the 0x0000 element (if any) 
+ *        of *each* Shadow Group. The parser will fail if the size is wrong !
+ * @param   mode Load mode to be used    
+ */
+   void SetLoadMode (int mode) { if (LoadMode != mode) 
+                                     LoadMode=mode, IsDocumentModified = true; }
+
+protected:
+// Methods
+   // Constructor and destructor are protected to forbid end user 
+   // to instanciate from this class Document (only gdcm::File and
+   // gdcm::DicomDir are meaningfull).
+   Document();
+   GDCM_LEGACY( Document( std::string const &filename ) );
+   virtual ~Document();
+
+   uint16_t ReadInt16() throw ( FormatError );
+   uint32_t ReadInt32() throw ( FormatError );
+   void     SkipBytes(uint32_t);
+   int ComputeGroup0002Length( );
+
+// Variables
+   /// Refering underlying filename.
+   std::string Filename;
+
+   /// \brief Swap code gives an information on the byte order of a 
+   ///  supposed to be an int32, as it's read on disc 
+   /// (depending on the image Transfer Syntax *and* on the processor endianess)
+   /// as opposed as it should in memory to be dealt as an int32.
+   /// For instance :
+   /// - a 'Little Endian' image, read with a little endian processor
+   /// will have a SwapCode= 1234 (the order is OK; nothing to do)
+   /// - a 'Little Endian' image, read with a big endian procesor
+   /// will have a SwapCode= 4321 (the order is wrong; int32 an int16 must be
+   /// swapped)
+   /// note : values 2143, 4321, 3412 remain for the ACR-NEMA time, and
+   /// the well known 'Bad Big Endian' and 'Bad Little Endian' codes
+   int SwapCode;
+
+   ///\brief whether we already parsed group 0002 (Meta Elements)
+   bool Group0002Parsed;
+
+   ///\brief whether file has a DCM Preamble
+   bool HasDCMPreamble;
+
+   /// File Pointer, opened during Document parsing.
+   std::ifstream *Fp;
+
+   /// ACR, ACR_LIBIDO, ExplicitVR, ImplicitVR, Unknown
+   FileType Filetype;  
+
+   /// After opening the file, we read HEADER_LENGTH_TO_READ bytes.
+   static const unsigned int HEADER_LENGTH_TO_READ; 
+   /// \brief Elements whose value is longer than MAX_SIZE_LOAD_ELEMENT_VALUE
+   /// are NOT loaded.
+   static const unsigned int MAX_SIZE_LOAD_ELEMENT_VALUE;
+
+   /// User supplied list of elements to Anonymize
+   ListElements UserAnonymizeList;
+
+   /// User supplied list of elements to force Load
+   ListElements UserForceLoadList;
+
+   /// \brief Bit string integer (each one considered as a boolean)
+   ///        Bit 0 : Skip Sequences,    if possible
+   ///        Bit 1 : Skip Shadow Groups if possible
+   ///        Probabely, some more to add
+   int LoadMode;
+   
+   /// \brief Whether the gdcm::Document is already parsed/loaded :
+   /// False from the creation of the gdcm::Document untill 
+   ///   gdcm::Document:Load()
+   bool IsDocumentAlreadyLoaded; // FIXME : probabely useless now
+
+   /// Whether the gdcm::Document was modified since the last Load()
+   bool IsDocumentModified;
+
+private:
+// Methods
+   void Initialize();
+   bool DoTheLoadingDocumentJob();
+   // Read
+   void ParseDES(DocEntrySet *set, long offset, long l_max, bool delim_mode);
+   void ParseSQ (SeqEntry *seq,    long offset, long l_max, bool delim_mode);
+
+   void LoadDocEntry         (DocEntry *e, bool forceLoad = false);
+   void FindDocEntryLength   (DocEntry *e) throw ( FormatError );
+   uint32_t FindDocEntryLengthOBOrOW() throw( FormatUnexpected );
+   std::string FindDocEntryVR();
+   bool CheckDocEntryVR      (VRKey k);
+
+   std::string GetDocEntryValue  (DocEntry *entry);
+   std::string GetDocEntryUnvalue(DocEntry *entry);
+
+   void SkipDocEntry          (DocEntry *entry);
+   void SkipToNextDocEntry    (DocEntry *entry);
+
+   void FixDocEntryFoundLength(DocEntry *entry, uint32_t l);
+   bool IsDocEntryAnInteger   (DocEntry *entry);
+
+   bool CheckSwap();
+   void SwitchByteSwapCode();
+
+   // DocEntry related utilities
+   DocEntry *ReadNextDocEntry();
+
+   void HandleBrokenEndian  (uint16_t &group, uint16_t &elem);
+   void HandleOutOfGroup0002(uint16_t &group, uint16_t &elem);
+   DocEntry *Backtrack(DocEntry *docEntry);
+
+// Variables
+   /// Public dictionary used to parse this header
+   Dict *RefPubDict;
+   /// \brief Optional "shadow dictionary" (private elements) used to parse
+   /// this header
+   Dict *RefShaDict;
+
+   /// \brief Size threshold above which an element value will NOT be loaded
+   /// in memory (to avoid loading the image/volume itself). By default,
+   /// this upper bound is fixed to 1024 bytes (which might look reasonable
+   /// when one considers the definition of the various VR contents).
+   uint32_t MaxSizeLoadEntry;
+
+//  uint32_t GenerateFreeTagKeyInGroup(uint16_t group);
+//  void BuildFlatHashTableRecurse( TagDocEntryHT &builtHT,
+//                                  DocEntrySet *set );
+
+};
+
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmElementSet.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmElementSet.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..998c578d602ff105c2c5e3de54193ea181217f42
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmElementSet.cxx
@@ -0,0 +1,220 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmElementSet.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.5 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmElementSet.h"
+#include "gdcmDebug.h"
+#include "gdcmValEntry.h"
+#include "gdcmBinEntry.h"
+#include "gdcmSeqEntry.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor for a given ElementSet
+ */
+ElementSet::ElementSet(int depthLevel) 
+          : DocEntrySet()
+{
+  (void)depthLevel;
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+ElementSet::~ElementSet() 
+{
+   ClearEntry();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+  * \brief   Writes the Header Entries (Dicom Elements)
+  *          from the H Table
+  * @param fp ofstream to write to  
+  * @param filetype filetype
+  */ 
+void ElementSet::WriteContent(std::ofstream *fp, FileType filetype)
+{
+   for (TagDocEntryHT::const_iterator i = TagHT.begin(); 
+                                     i != TagHT.end(); 
+                                    ++i)
+   {
+      i->second->WriteContent(fp, filetype);
+   } 
+}
+
+/**
+ * \brief   add a new Dicom Element pointer to the H Table
+ * @param   newEntry entry to add
+ */
+bool ElementSet::AddEntry(DocEntry *newEntry)
+{
+   const TagKey &key = newEntry->GetKey();
+
+   if ( TagHT.count(key) == 1 )
+   {
+      gdcmWarningMacro( "Key already present: " << key );
+      return false;
+   }
+   else
+   {
+      TagHT.insert(TagDocEntryHT::value_type(newEntry->GetKey(), newEntry));
+      return true;
+   }
+}
+
+/**
+ * \brief   Clear the hash table from given entry AND delete the entry.
+ * @param   entryToRemove Entry to remove AND delete.
+ */
+bool ElementSet::RemoveEntry( DocEntry *entryToRemove)
+{
+   const TagKey &key = entryToRemove->GetKey();
+   if ( TagHT.count(key) == 1 )
+   {
+      TagHT.erase(key);
+      delete entryToRemove;
+      return true;
+   }
+
+   gdcmWarningMacro( "Key not present : " << key);
+   return false ;
+}
+
+/**
+ * \brief   Clear the hash table from given entry BUT keep the entry.
+ * @param   entryToRemove Entry to remove.
+ */
+bool ElementSet::RemoveEntryNoDestroy(DocEntry *entryToRemove)
+{
+   const TagKey &key = entryToRemove->GetKey();
+   if ( TagHT.count(key) == 1 )
+   {
+      TagHT.erase(key);
+      //gdcmWarningMacro( "One element erased.");
+      return true;
+   }
+
+   gdcmWarningMacro( "Key not present " << key);
+   return false ;
+}
+
+/**
+ * \brief   delete all entries in the ElementSet
+ */
+void ElementSet::ClearEntry()
+{
+   for(TagDocEntryHT::iterator cc = TagHT.begin();cc != TagHT.end(); ++cc)
+   {
+      if ( cc->second )
+      {
+         delete cc->second;
+      }
+   }
+   TagHT.clear();
+}
+
+/**
+ * \brief   Get the first entry while visiting *the* 'zero level' DocEntrySet
+ *              (DocEntries out of any Sequence)
+ * \return  The first DocEntry if found, otherwhise NULL
+ */
+DocEntry *ElementSet::GetFirstEntry()
+{
+   ItTagHT = TagHT.begin();
+   if (ItTagHT != TagHT.end())
+      return  ItTagHT->second;
+   return NULL;
+}
+
+/**
+ * \brief   Get the next entry while visiting *the* 'zero level' DocEntrySet
+ *              (DocEntries out of any Sequence) 
+ * \note : meaningfull only if GetFirstEntry already called 
+ * \return  The next DocEntry if found, otherwhise NULL
+ */
+DocEntry *ElementSet::GetNextEntry()
+{
+   gdcmAssertMacro (ItTagHT != TagHT.end());
+
+   ++ItTagHT;
+   if (ItTagHT != TagHT.end())
+      return  ItTagHT->second;
+   return NULL;
+}
+
+/**
+ * \brief  retrieves a Dicom Element using (group, element)
+ * @param   group  Group number of the searched Dicom Element 
+ * @param   elem Element number of the searched Dicom Element 
+ * @return  
+ */
+DocEntry *ElementSet::GetDocEntry(uint16_t group, uint16_t elem) 
+{
+   TagKey key = DictEntry::TranslateToKey(group, elem);
+   TagDocEntryHT::iterator it = TagHT.find(key);
+
+   if ( it!=TagHT.end() )
+      return it->second;
+   return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+  * \brief   Prints the Header Entries (Dicom Elements) from the H Table
+  * @param os ostream to write to  
+  * @param indent Indentation string to be prepended during printing
+  */ 
+void ElementSet::Print(std::ostream &os, std::string const & )
+{
+   // Let's change the 'warning value' for Pixel Data,
+   // to avoid human reader to be confused by 'gdcm::NotLoaded'.   
+   gdcm::BinEntry *pixelElement = GetBinEntry(0x7fe0,0x0010);
+   if ( pixelElement != 0 )
+   {
+      pixelElement->SetValue( gdcm::GDCM_PIXELDATA);
+   }
+
+   for( TagDocEntryHT::const_iterator i = TagHT.begin(); i != TagHT.end(); ++i)
+   {
+      DocEntry *entry = i->second;
+
+      entry->SetPrintLevel(PrintLevel);
+      entry->Print(os);   
+
+      if ( dynamic_cast<SeqEntry*>(entry) )
+      {
+         // Avoid the newline for a sequence:
+         continue;
+      }
+      os << std::endl;
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmElementSet.h b/Utilities/ITK/Utilities/gdcm/src/gdcmElementSet.h
new file mode 100644
index 0000000000000000000000000000000000000000..6451fbc408de934f36695a9b2f4b79702ba37662
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmElementSet.h
@@ -0,0 +1,80 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmElementSet.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.6 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMELEMENTSET_H
+#define GDCMELEMENTSET_H
+
+#include "gdcmDocEntrySet.h"
+
+#include <map>
+#include <iostream>
+#include <fstream>
+
+namespace gdcm 
+{
+class ValEntry;
+class BinEntry;
+class SeqEntry;
+
+typedef std::map<TagKey, DocEntry *> TagDocEntryHT;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief
+ * \ref ElementSet is based on the STL map<> container
+ * (see \ref ElementSet::TagHT), as opposed to \ref SQItem
+ * which is based on an STL list container (see \ref ListDocEntry).
+ * It contains the 'zero-level- DocEntry (out of any Dicom Sequence)
+ */
+class GDCM_EXPORT ElementSet : public DocEntrySet
+{
+public:
+   ElementSet(int);
+   ~ElementSet();
+
+   virtual void Print(std::ostream &os = std::cout, 
+                      std::string const &indent = "" ); 
+
+   void WriteContent(std::ofstream *fp, FileType filetype); 
+
+   bool AddEntry(DocEntry *Entry);
+   bool RemoveEntry(DocEntry *EntryToRemove);
+   bool RemoveEntryNoDestroy(DocEntry *EntryToRemove);
+   void ClearEntry();
+   
+   DocEntry *GetFirstEntry();
+   DocEntry *GetNextEntry();
+   DocEntry *GetDocEntry(uint16_t group, uint16_t elem);
+   /// Tells us if the ElementSet contains no entry
+   bool IsEmpty() { return TagHT.empty(); }
+
+protected:
+
+private:
+// Variables
+   /// Hash Table (map), to provide fast access
+   TagDocEntryHT TagHT;
+   /// iterator, used to visit the TagHT variable
+   TagDocEntryHT::iterator ItTagHT;
+   /// iterator, used to visit the TagHT variable, seeking only for ValEntries
+   TagDocEntryHT::iterator ItValEntryTagHT;
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmException.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmException.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..fc3d8f76022414d6842807b7b97f86bc12d9881b
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmException.cxx
@@ -0,0 +1,143 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmException.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmException.h"
+
+#include <typeinfo>
+#include <stdlib.h> // for exit
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Exception
+/**
+ * \brief constructor
+ * @param f f
+ * @param msg msg 
+ */
+Exception::Exception(const std::string &f, const std::string &msg) throw()
+#ifdef __GNUC__
+   try
+#endif
+   : From(f), Error(msg) 
+   {
+   }
+#ifdef __GNUC__
+   catch(...) 
+   {
+      fatal("Exception::Exception(const std::string&, const std::string&, const std::string&)");
+   }
+#endif
+
+/**
+ * \brief fatal
+ * @param from from
+ */
+void Exception::fatal(const char *from) throw() 
+{
+   try
+   {
+      std::cerr << "Fatal: exception received in " << from 
+                << " while handling exception." << std::endl;
+      exit(-1);
+   }
+   catch(...)
+   {
+      try
+      {
+         std::cerr << "Fatal: exception received in Exception::fatal while handling exception."
+                   << std::endl;
+         exit(-1);
+      }
+      catch(...)
+      {
+         exit(-1);
+      }
+   }
+}
+
+/**
+ * \brief getName
+ * @return string
+ */
+std::string Exception::getName() const throw()
+{
+   try
+   {
+#if defined(__GNUC__) && 0   // GNU C++ compiler class name demangling
+      unsigned int nested = 1, i, nb;
+      int offset;
+      std::string one;
+
+      std::string name;
+      std::string iname = typeid(*this).name();
+      if ( iname[0] == 'Q' )
+      {
+         nested = iname[1] - '0';
+         iname = std::string(iname, 2, std::string::npos);
+      }
+      for(i = 0; i < nested; i++)
+      {
+         ::sscanf(iname.c_str(), "%u%n", &nb, &offset);
+         iname = std::string(iname, offset, std::string::npos);
+         name += std::string(iname, 0, nb);
+         if ( i + 1 < nested) name += "::";
+         iname = std::string(iname, nb, std::string::npos );
+      }
+      return name;
+#else           // no class name demangling
+      std::string name = typeid(*this).name();
+      return name;
+#endif
+   }
+   catch(...) 
+   {
+      fatal("Exception::getName(std::string &)");
+      return "";
+   }
+}
+
+/**
+ * \brief Exception
+ */
+Exception::operator const char *() const throw() 
+{
+   return getName().c_str();
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief Exception::operator <<
+ * @param os ostream to write to
+ * @param e exception to raise
+ */
+std::ostream& operator<<(std::ostream &os, const Exception &e) 
+{
+   try 
+   {
+      os << "Exception " << e.getName() << " thrown: " << e.getError() << std::endl;
+   }
+   catch(...) 
+   {
+      Exception::fatal("operator<<(std::ostream &, const Exception&)");
+   }
+   return os;
+}
+
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmException.h b/Utilities/ITK/Utilities/gdcm/src/gdcmException.h
new file mode 100644
index 0000000000000000000000000000000000000000..632ee3048c086342ea9aad2268a80bf721bd8af5
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmException.h
@@ -0,0 +1,139 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmException.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCM_EXCEPTION_H
+#define GDCM_EXCEPTION_H
+
+#include "gdcmCommon.h"
+
+#include <string>
+#include <iostream>
+#include <exception>
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief Any exception thrown in the gdcm library
+ */
+class GDCM_EXPORT Exception : public std::exception
+{
+public:
+   /*
+    * \brief Builds an exception with minimal information: name of the thrower
+    *        method and error message
+    * @param from name of the thrower
+    * @param error error description string
+    */
+   explicit Exception(const std::string &from, const std::string &error = "")
+      throw();
+
+   /**
+    * \brief virtual destructor makes this class dynamic
+    */
+   virtual ~Exception() throw() {}
+
+   /// exception caught within exception class: print error message and die
+   static void fatal(const char *from) throw();
+
+   /// returns error message
+   const std::string &getError() const throw() { return Error;}
+
+   /// try to discover this (dynamic) class name
+   virtual std::string getName() const throw();
+
+   /// returns exception name string (overloads std::exception::what)
+   virtual const char *what() const throw() { return (const char *) *this;}
+
+   /// returns exception name string
+   operator const char *() const throw();
+
+   friend std::ostream &operator<<(std::ostream &os, const Exception &e);
+
+protected:
+   /// error message part 1
+   std::string From;
+   /// error message part 2
+   std::string Error;
+};
+
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief File error exception thrown in the gdcm library
+ */
+class GDCM_EXPORT FileError : public Exception
+{
+public:
+   /**
+    * \brief Builds an file-related exception with minimal information: name of
+    *               the thrower method and error message
+    * @param from name of the thrower
+    * @param error error description string
+    */
+   explicit FileError(const std::string &from,
+                          const std::string &error = "File error")
+      throw() : Exception(from, error) { }
+};
+
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief Unexpected file format exception
+ */
+class GDCM_EXPORT FormatUnexpected : public Exception
+{
+public:
+   /// \brief Builds a file-related exception with minimal information:
+   /// name of the thrower method and error message
+   /// @param from name of the thrower
+   /// @param error error description string
+   explicit FormatUnexpected(const std::string &from,
+                             const std::string &error = "Unexpected file format")
+      throw() : Exception( from, error ) { }
+};
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief Invalid file format exception
+ */
+class GDCM_EXPORT FormatError : public FormatUnexpected
+{
+public:
+   /// \brief Builds a file-related exception with minimal information:
+   /// name of the thrower method and error message
+   /// @param from name of the thrower
+   /// @param error error description string
+   explicit FormatError(const std::string &from,
+                        const std::string &error = "Invalid file format")
+      throw() : FormatUnexpected( from, error ) { }
+};
+
+//-----------------------------------------------------------------------------
+/* prints exception stack on output stream
+ * @param os output stream
+ * @param e exception to print
+ * @returns output stream os
+ */
+std::ostream& operator<<(std::ostream &os, const Exception &e);
+
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif // GDCM_EXCEPTION_H
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmFile.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmFile.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c4c2eee0dcc5457c07991a03f85fccb7e2a898f1
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmFile.cxx
@@ -0,0 +1,1898 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmFile.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.14 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+//
+// --------------  Remember ! ----------------------------------
+//
+// Image Position (Patient)                            (0020,0032):
+// If not found (ACR_NEMA) we try Image Position       (0020,0030)
+// If not found (ACR-NEMA), we consider Slice Location (0020,1041)
+//                                   or Location       (0020,0050) 
+//                                   as the Z coordinate, 
+// 0. for all the coordinates if nothing is found
+//
+// Image Position (Patient) (0020,0032) VM=3
+// -->
+//  The attribute Patient Orientation (0020,0020) from the General Image Module 
+// is of type 2C and has the condition Required if image does not require 
+// Image Orientation (0020,0037) and Image Position (0020,0032). 
+// However, if the image does require the attributes 
+// - Image Orientation (Patient) (0020,0037), VM=6
+// - Image Position (Patient)    (0020,0032), VM=3
+// then attribute Patient Orientation (0020,0020) should not be present
+//  in the images.
+//
+// Remember also :
+// Patient Position (0018,5100) values :
+
+//  HFS   = Head First-Supine, where increasing (positive axis direction) :
+//     X -> to the direction pointed to by the patient's oustretched left arm
+//     Y -> to the anterior-to-posterior direction in the patient's body
+//     Z -> to the feet-to-head direction in the patient's body
+
+//  HFP   = Head First-Prone, where increasing (positive axis direction) :
+//     X -> to the direction pointed to by the patient's oustretched left arm
+//     Y -> to the anterior-to-posterior direction in the patient's body
+//     Z -> to the feet-to-head direction in the patient's body
+
+//  FFS  = Feet First-Supine, where increasing (positive axis direction) :
+//     X -> to the direction pointed to by the patient's oustretched left arm
+//     Y -> to the anterior-to-posterion direction in the patient's body
+//     Z -> to the feet-to-head direction in the patient's body
+
+//  FFP  = Feet First-Prone, where increasing (positive axis direction) :
+//     X -> to the direction pointed to by the patient's oustretched left arm
+//     Y -> to the posterior-to-anterior direction in the patient's body
+//     Z -> to the feet-to-head direction in the patient's body
+
+// HFDR = Head First-Decubitus Right
+// HFDL = Head First-Decubitus Left
+// FFDR = Feet First-Decubitus Right
+// FFDL = Feet First-Decubitus Left
+
+//  we can also find (non standard!)     
+
+// SEMIERECT
+// SUPINE
+
+// CS 2 Patient Orientation (0020 0020)
+//    When the coordinates of the image 
+//    are always present, this field is almost never used.
+//    Better we don't trust it too much ...
+//    Found Values are :
+//     L\P
+//     L\FP
+//     P\F
+//     L\F
+//     P\FR
+//     R\F
+//
+// (0020|0037) [Image Orientation (Patient)] [1\0\0\0\1\0 ]
+
+               
+// ---------------------------------------------------------------
+//
+#include "gdcmFile.h"
+#include "gdcmGlobal.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+#include "gdcmTS.h"
+#include "gdcmValEntry.h"
+#include "gdcmBinEntry.h"
+#include "gdcmSeqEntry.h"
+#include "gdcmRLEFramesInfo.h"
+#include "gdcmJPEGFragmentsInfo.h"
+
+#include <vector>
+#include <stdio.h>  //sscanf
+#include <stdlib.h> // for atoi
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+
+/**
+ * \brief Constructor used when we want to generate dicom files from scratch
+ */
+File::File():
+   Document()
+{
+   RLEInfo  = new RLEFramesInfo;
+   JPEGInfo = new JPEGFragmentsInfo;
+   GrPixel  = 0x7fe0;  // to avoid further troubles
+   NumPixel = 0x0010;
+   BasicOffsetTableItemValue = 0;
+}
+
+
+/**
+ * \brief   Canonical destructor.
+ */
+File::~File()
+{
+   if ( RLEInfo )
+      delete RLEInfo;
+   if ( JPEGInfo )
+      delete JPEGInfo;
+   delete[] BasicOffsetTableItemValue;
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Loader  
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
+ */
+bool File::Load( ) 
+{
+   if ( ! this->Document::Load( ) )
+      return false;
+
+    return DoTheLoadingJob( );   
+}
+
+/**
+ * \brief   Does the Loading Job (internal use only)
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
+ */
+bool File::DoTheLoadingJob( ) 
+{
+   // for some ACR-NEMA images GrPixel, NumPixel is *not* 7fe0,0010
+   // We may encounter the 'RETired' (0x0028, 0x0200) tag
+   // (Image Location") . This entry contains the number of
+   // the group that contains the pixel data (hence the "Pixel Data"
+   // is found by indirection through the "Image Location").
+   // Inside the group pointed by "Image Location" the searched element
+   // is conventionally the element 0x0010 (when the norm is respected).
+   // When the "Image Location" is missing we default to group 0x7fe0.
+   // Note: this IS the right place for the code
+ 
+   // Image Location
+   const std::string &imgLocation = GetEntryValue(0x0028, 0x0200);
+   if ( imgLocation == GDCM_UNFOUND )
+   {
+      // default value
+      GrPixel = 0x7fe0;
+   }
+   else
+   {
+      GrPixel = (uint16_t) atoi( imgLocation.c_str() );
+   }   
+
+   // sometimes Image Location value doesn't follow
+   // the supposed processor endianness.
+   // see gdcmData/cr172241.dcm
+   if ( GrPixel == 0xe07f )
+   {
+      GrPixel = 0x7fe0;
+   }
+
+   if ( GrPixel != 0x7fe0 )
+   {
+      // This is a kludge for old dirty Philips imager.
+      NumPixel = 0x1010;
+   }
+   else
+   {
+      NumPixel = 0x0010;
+   }
+
+   // Now, we know GrPixel and NumPixel.
+   // Let's create a VirtualDictEntry to allow a further VR modification
+   // and force VR to match with BitsAllocated.
+   DocEntry *entry = GetDocEntry(GrPixel, NumPixel); 
+   if ( entry != 0 )
+   {
+      // Compute the RLE or JPEG info
+      OpenFile();
+      const std::string &ts = GetTransferSyntax();
+      Fp->seekg( entry->GetOffset(), std::ios::beg );
+      if ( Global::GetTS()->IsRLELossless(ts) ) 
+         ComputeRLEInfo();
+      else if ( Global::GetTS()->IsJPEG(ts) )
+         ComputeJPEGFragmentInfo();
+      CloseFile();
+
+      // Create a new BinEntry to change the DictEntry
+      // The changed DictEntry will have 
+      // - a correct PixelVR OB or OW)
+      // - the name to "Pixel Data"
+      BinEntry *oldEntry = dynamic_cast<BinEntry *>(entry);
+      if (oldEntry)
+      {
+         std::string PixelVR;
+         // 8 bits allocated is a 'O Bytes' , as well as 24 (old ACR-NEMA RGB)
+         // more than 8 (i.e 12, 16) is a 'O Words'
+         if ( GetBitsAllocated() == 8 || GetBitsAllocated() == 24 ) 
+            PixelVR = "OB";
+         else
+            PixelVR = "OW";
+
+         // Change only made if usefull
+         if ( PixelVR != oldEntry->GetVR() )
+         {
+            DictEntry* newDict = NewVirtualDictEntry(GrPixel,NumPixel,
+                                                     PixelVR,"1","Pixel Data");
+
+            BinEntry *newEntry = new BinEntry(newDict);
+            newEntry->Copy(entry);
+            newEntry->SetBinArea(oldEntry->GetBinArea(),oldEntry->IsSelfArea());
+            oldEntry->SetSelfArea(false);
+
+            RemoveEntry(oldEntry);
+            AddEntry(newEntry);
+         }
+      }
+   }
+   return true;
+}
+/**
+ * \brief  This predicate, based on hopefully reasonable heuristics,
+ *         decides whether or not the current File was properly parsed
+ *         and contains the mandatory information for being considered as
+ *         a well formed and usable Dicom/Acr File.
+ * @return true when File is the one of a reasonable Dicom/Acr file,
+ *         false otherwise. 
+ */
+bool File::IsReadable()
+{
+   if ( !Document::IsReadable() )
+   {
+      return false;
+   }
+
+   const std::string &res = GetEntryValue(0x0028, 0x0005);
+   if ( res != GDCM_UNFOUND && atoi(res.c_str()) > 4 )
+   {
+      gdcmWarningMacro("Wrong Image Dimensions" << res);
+      return false; // Image Dimensions
+   }
+   bool b0028_0100 = true;
+   if ( !GetDocEntry(0x0028, 0x0100) )
+   {
+      gdcmWarningMacro("Bits Allocated (0028|0100) not found"); 
+      //return false; // "Bits Allocated"
+      b0028_0100 = false;
+   }
+   bool b0028_0101 = true;
+   if ( !GetDocEntry(0x0028, 0x0101) )
+   {
+      gdcmWarningMacro("Bits Stored (0028|0101) not found");
+      //return false; // "Bits Stored"
+      b0028_0101 = false;
+   }
+   bool b0028_0102 = true;
+   if ( !GetDocEntry(0x0028, 0x0102) )
+   {
+      gdcmWarningMacro("Hight Bit (0028|0102) not found"); 
+      //return false; // "High Bit"
+      b0028_0102 = false;
+   }
+   bool b0028_0103 = true;
+   if ( !GetDocEntry(0x0028, 0x0103) )
+   {
+      gdcmWarningMacro("Pixel Representation (0028|0103) not found");
+      //return false; // "Pixel Representation" i.e. 'Sign' ( 0 : unsigned, 1 : signed)
+      b0028_0103 = false;
+   }
+
+   if ( !b0028_0100 && !b0028_0101 && !b0028_0102 && !b0028_0103)
+   {
+      gdcmWarningMacro("Too much mandatory Tags missing !");
+      return false;
+   }
+
+   if ( !GetDocEntry(GrPixel, NumPixel) )
+   {
+      gdcmWarningMacro("Pixel Dicom Element " << std::hex <<
+                        GrPixel << "|" << NumPixel << "not found");
+      return false; // Pixel Dicom Element not found :-(
+   }
+   return true;
+}
+
+/**
+ * \brief gets the info from 0020,0013 : Image Number else 0.
+ * @return image number
+ */
+int File::GetImageNumber()
+{
+   //0020 0013 : Image Number
+   std::string strImNumber = GetEntryValue(0x0020,0x0013);
+   if ( strImNumber != GDCM_UNFOUND )
+   {
+      return atoi( strImNumber.c_str() );
+   }
+   return 0;   //Hopeless
+}
+
+/**
+ * \brief gets the info from 0008,0060 : Modality
+ * @return Modality Type
+ */
+ModalityType File::GetModality()
+{
+   // 0008 0060 : Modality
+   std::string strModality = GetEntryValue(0x0008,0x0060);
+   if ( strModality != GDCM_UNFOUND )
+   {
+           if ( strModality.find("AU")  < strModality.length()) return AU;
+      else if ( strModality.find("AS")  < strModality.length()) return AS;
+      else if ( strModality.find("BI")  < strModality.length()) return BI;
+      else if ( strModality.find("CF")  < strModality.length()) return CF;
+      else if ( strModality.find("CP")  < strModality.length()) return CP;
+      else if ( strModality.find("CR")  < strModality.length()) return CR;
+      else if ( strModality.find("CT")  < strModality.length()) return CT;
+      else if ( strModality.find("CS")  < strModality.length()) return CS;
+      else if ( strModality.find("DD")  < strModality.length()) return DD;
+      else if ( strModality.find("DF")  < strModality.length()) return DF;
+      else if ( strModality.find("DG")  < strModality.length()) return DG;
+      else if ( strModality.find("DM")  < strModality.length()) return DM;
+      else if ( strModality.find("DS")  < strModality.length()) return DS;
+      else if ( strModality.find("DX")  < strModality.length()) return DX;
+      else if ( strModality.find("ECG") < strModality.length()) return ECG;
+      else if ( strModality.find("EPS") < strModality.length()) return EPS;
+      else if ( strModality.find("FA")  < strModality.length()) return FA;
+      else if ( strModality.find("FS")  < strModality.length()) return FS;
+      else if ( strModality.find("HC")  < strModality.length()) return HC;
+      else if ( strModality.find("HD")  < strModality.length()) return HD;
+      else if ( strModality.find("LP")  < strModality.length()) return LP;
+      else if ( strModality.find("LS")  < strModality.length()) return LS;
+      else if ( strModality.find("MA")  < strModality.length()) return MA;
+      else if ( strModality.find("MR")  < strModality.length()) return MR;
+      else if ( strModality.find("NM")  < strModality.length()) return NM;
+      else if ( strModality.find("OT")  < strModality.length()) return OT;
+      else if ( strModality.find("PT")  < strModality.length()) return PT;
+      else if ( strModality.find("RF")  < strModality.length()) return RF;
+      else if ( strModality.find("RG")  < strModality.length()) return RG;
+      else if ( strModality.find("RTDOSE")   
+                                        < strModality.length()) return RTDOSE;
+      else if ( strModality.find("RTIMAGE")  
+                                        < strModality.length()) return RTIMAGE;
+      else if ( strModality.find("RTPLAN")
+                                        < strModality.length()) return RTPLAN;
+      else if ( strModality.find("RTSTRUCT") 
+                                        < strModality.length()) return RTSTRUCT;
+      else if ( strModality.find("SM")  < strModality.length()) return SM;
+      else if ( strModality.find("ST")  < strModality.length()) return ST;
+      else if ( strModality.find("TG")  < strModality.length()) return TG;
+      else if ( strModality.find("US")  < strModality.length()) return US;
+      else if ( strModality.find("VF")  < strModality.length()) return VF;
+      else if ( strModality.find("XA")  < strModality.length()) return XA;
+      else if ( strModality.find("XC")  < strModality.length()) return XC;
+
+      else
+      {
+         /// \todo throw error return value ???
+         /// specified <> unknown in our database
+         return Unknow;
+      }
+   }
+   return Unknow;
+}
+
+/**
+ * \brief   Retrieve the number of columns of image.
+ * @return  The encountered size when found, 0 by default.
+ *          0 means the file is NOT USABLE. The caller will have to check
+ */
+int File::GetXSize()
+{
+   const std::string &strSize = GetEntryValue(0x0028,0x0011);
+   if ( strSize == GDCM_UNFOUND )
+   {
+      return 0;
+   }
+   return atoi( strSize.c_str() );
+}
+
+/**
+ * \brief   Retrieve the number of lines of image.
+ * \warning The defaulted value is 1 as opposed to File::GetXSize()
+ * @return  The encountered size when found, 1 by default 
+ *          (The ACR-NEMA file contains a Signal, not an Image).
+ */
+int File::GetYSize()
+{
+   const std::string &strSize = GetEntryValue(0x0028,0x0010);
+   if ( strSize != GDCM_UNFOUND )
+   {
+      return atoi( strSize.c_str() );
+   }
+   if ( IsDicomV3() )
+   {
+      return 0;
+   }
+
+   // The Rows (0028,0010) entry was optional for ACR/NEMA.
+   // (at least some images didn't have it.)
+   // It might hence be a signal (1D image). So we default to 1:
+   return 1;
+}
+
+/**
+ * \brief   Retrieve the number of planes of volume or the number
+ *          of frames of a multiframe.
+ * \warning When present we consider the "Number of Frames" as the third
+ *          dimension. When missing we consider the third dimension as
+ *          being the ACR-NEMA "Planes" tag content.
+ * @return  The encountered size when found, 1 by default (single image).
+ */
+int File::GetZSize()
+{
+   // Both  DicomV3 and ACR/Nema consider the "Number of Frames"
+   // as the third dimension.
+   const std::string &strSize = GetEntryValue(0x0028,0x0008);
+   if ( strSize != GDCM_UNFOUND )
+   {
+      return atoi( strSize.c_str() );
+   }
+
+   // We then consider the "Planes" entry as the third dimension 
+   const std::string &strSize2 = GetEntryValue(0x0028,0x0012);
+   if ( strSize2 != GDCM_UNFOUND )
+   {
+      return atoi( strSize2.c_str() );
+   }
+   return 1;
+}
+
+/**
+  * \brief gets the info from 0018,1164 : ImagerPixelSpacing
+  *                      then 0028,0030 : Pixel Spacing
+  *             else 1.0
+  * @return X dimension of a pixel
+  */
+float File::GetXSpacing()
+{
+   float xspacing = 1.0;
+   float yspacing = 1.0;
+   int nbValues;
+
+   // To follow David Clunie's advice, we first check ImagerPixelSpacing
+
+   const std::string &strImagerPixelSpacing = GetEntryValue(0x0018,0x1164);
+   if ( strImagerPixelSpacing != GDCM_UNFOUND )
+   {
+      if ( ( nbValues = sscanf( strImagerPixelSpacing.c_str(), 
+            "%f\\%f", &yspacing, &xspacing)) != 2 )
+      {
+         // if no values, xspacing is set to 1.0
+         if ( nbValues == 0 )
+            xspacing = 1.0;
+         // if single value is found, xspacing is defaulted to yspacing
+         if ( nbValues == 1 )
+            xspacing = yspacing;
+
+         if ( xspacing == 0.0 )
+            xspacing = 1.0;
+      }  
+      return xspacing;
+   }
+
+   const std::string &strSpacing = GetEntryValue(0x0028,0x0030);
+
+   if ( strSpacing == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro( "Unfound Pixel Spacing (0028,0030)" );
+      return 1.;
+   }
+
+   if ( ( nbValues = sscanf( strSpacing.c_str(), 
+         "%f \\%f ", &yspacing, &xspacing)) != 2 )
+   {
+      // if no values, xspacing is set to 1.0
+      if ( nbValues == 0 )
+         xspacing = 1.0;
+      // if single value is found, xspacing is defaulted to yspacing
+      if ( nbValues == 1 )
+         xspacing = yspacing;
+
+      if ( xspacing == 0.0 )
+         xspacing = 1.0;
+   }
+   return xspacing;
+
+   // to avoid troubles with David Clunie's-like images (at least one)
+   if ( xspacing == 0.0 && yspacing == 0.0)
+      return 1.0;
+
+   if ( xspacing == 0.0)
+   {
+      gdcmWarningMacro("gdcmData/CT-MONO2-8-abdo.dcm-like problem");
+      // seems to be a bug in the header ...
+      nbValues = sscanf( strSpacing.c_str(), "%f \\0\\%f ", &yspacing, &xspacing);
+      gdcmAssertMacro( nbValues == 2 );
+   }
+
+   return xspacing;
+}
+
+/**
+  * \brief gets the info from 0018,1164 : ImagerPixelSpacing
+  *               then from   0028,0030 : Pixel Spacing                         
+  *             else 1.0
+  * @return Y dimension of a pixel
+  */
+float File::GetYSpacing()
+{
+   float yspacing = 1.0;
+   int nbValues;
+   // To follow David Clunie's advice, we first check ImagerPixelSpacing
+
+   const std::string &strImagerPixelSpacing = GetEntryValue(0x0018,0x1164);
+   if ( strImagerPixelSpacing != GDCM_UNFOUND )
+   {
+      nbValues = sscanf( strImagerPixelSpacing.c_str(), "%f", &yspacing);
+   
+   // if sscanf cannot read any float value, it won't affect yspacing
+      if ( nbValues == 0 )
+            yspacing = 1.0;
+
+      if ( yspacing == 0.0 )
+            yspacing = 1.0;
+
+      return yspacing;  
+   }
+
+   std::string strSpacing = GetEntryValue(0x0028,0x0030);  
+   if ( strSpacing == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro("Unfound Pixel Spacing (0028,0030)");
+      return 1.;
+    }
+
+   // if sscanf cannot read any float value, it won't affect yspacing
+   nbValues = sscanf( strSpacing.c_str(), "%f", &yspacing);
+
+   // if no values, yspacing is set to 1.0
+   if ( nbValues == 0 )
+      yspacing = 1.0;
+
+   if ( yspacing == 0.0 )
+      yspacing = 1.0;
+
+   return yspacing;
+} 
+
+/**
+ * \brief gets the info from 0018,0088 : Space Between Slices
+ *                 else from 0018,0050 : Slice Thickness
+ *                 else 1.0
+ *
+ * When an element is missing, we suppose slices join together
+ * (no overlapping, no interslice gap) but we have no way to check it !
+ * For *Dicom* images, ZSpacing *should be* calculated using 
+ * XOrigin, YOrigin, ZOrigin (of the top left image corner)
+ * of 2 consecutive images, and the Orientation
+ * Computing ZSpacing on a single image is not really meaningfull ! 
+ * @return Z dimension of a voxel-to be
+ */
+float File::GetZSpacing()
+{
+   // Spacing Between Slices : distance between the middle of 2 slices
+   // Slices may be :
+   //   jointives     (Spacing between Slices = Slice Thickness)
+   //   overlapping   (Spacing between Slices < Slice Thickness)
+   //   disjointes    (Spacing between Slices > Slice Thickness)
+   // Slice Thickness : epaisseur de tissus sur laquelle est acquis le signal
+   //   It only concerns the MRI guys, not people wanting to visualize volumes
+   //   If Spacing Between Slices is missing, 
+   //   we suppose slices joint together
+
+   // --->
+   // ---> Warning :
+   // --->
+   
+  //
+  // For *Dicom* images, ZSpacing should be calculated using 
+  // XOrigin, YOrigin, ZOrigin (of the top left image corner)
+  // of 2 consecutive images, and the Orientation
+  // 
+  // Computing ZSpacing on a single image is not really meaningfull !
+  
+   const std::string &strSpacingBSlices = GetEntryValue(0x0018,0x0088);
+
+   if ( strSpacingBSlices == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro("Unfound Spacing Between Slices (0018,0088)");
+      const std::string &strSliceThickness = GetEntryValue(0x0018,0x0050);       
+      if ( strSliceThickness == GDCM_UNFOUND )
+      {
+         gdcmWarningMacro("Unfound Slice Thickness (0018,0050)");
+         return 1.0;
+      }
+      else
+      {
+         // if no 'Spacing Between Slices' is found, 
+         // we assume slices join together
+         // (no overlapping, no interslice gap)
+         // if they don't, we're fucked up
+         return (float)atof( strSliceThickness.c_str() );
+      }
+   }
+   //else
+   
+   float zsp = (float)atof( strSpacingBSlices.c_str());
+   if (zsp == 0.0) // last change not to break further computations ...
+      zsp = 1.0;
+   return zsp;
+}
+
+/**
+ * \brief gets the info from 0020,0032 : Image Position Patient
+ *                 else from 0020,0030 : Image Position (RET)
+ *                 else 0.
+ * @return up-left image corner X position
+ */
+float File::GetXOrigin()
+{
+   float xImPos, yImPos, zImPos;  
+   std::string strImPos = GetEntryValue(0x0020,0x0032);
+
+   if ( strImPos == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro( "Unfound Image Position Patient (0020,0032)");
+      strImPos = GetEntryValue(0x0020,0x0030); // For ACR-NEMA images
+      if ( strImPos == GDCM_UNFOUND )
+      {
+         gdcmWarningMacro( "Unfound Image Position (RET) (0020,0030)");
+         return 0.0;
+      }
+   }
+
+   if ( sscanf( strImPos.c_str(), "%f \\%f \\%f ", &xImPos, &yImPos, &zImPos) != 3 )
+   {
+      return 0.0;
+   }
+
+   return xImPos;
+}
+
+/**
+ * \brief gets the info from 0020,0032 : Image Position Patient
+ *                 else from 0020,0030 : Image Position (RET)
+ *                 else 0.
+ * @return up-left image corner Y position
+ */
+float File::GetYOrigin()
+{
+   float xImPos, yImPos, zImPos;
+   std::string strImPos = GetEntryValue(0x0020,0x0032);
+
+   if ( strImPos == GDCM_UNFOUND)
+   {
+      gdcmWarningMacro( "Unfound Image Position Patient (0020,0032)");
+      strImPos = GetEntryValue(0x0020,0x0030); // For ACR-NEMA images
+      if ( strImPos == GDCM_UNFOUND )
+      {
+         gdcmWarningMacro( "Unfound Image Position (RET) (0020,0030)");
+         return 0.;
+      }  
+   }
+
+   if ( sscanf( strImPos.c_str(), "%f \\%f \\%f ", &xImPos, &yImPos, &zImPos) != 3 )
+   {
+      return 0.;
+   }
+
+   return yImPos;
+}
+
+/**
+ * \brief gets the info from 0020,0032 : Image Position Patient
+ *                 else from 0020,0030 : Image Position (RET)
+ *                 else from 0020,1041 : Slice Location
+ *                 else from 0020,0050 : Location
+ *                 else 0.
+ * @return up-left image corner Z position
+ */
+float File::GetZOrigin()
+{
+   float xImPos, yImPos, zImPos; 
+   std::string strImPos = GetEntryValue(0x0020,0x0032);
+
+   if ( strImPos != GDCM_UNFOUND )
+   {
+      if ( sscanf( strImPos.c_str(), "%f \\%f \\%f ", &xImPos, &yImPos, &zImPos) != 3)
+      {
+         gdcmWarningMacro( "Wrong Image Position Patient (0020,0032)");
+         return 0.;  // bug in the element 0x0020,0x0032
+      }
+      else
+      {
+         return zImPos;
+      }
+   }
+
+   strImPos = GetEntryValue(0x0020,0x0030); // For ACR-NEMA images
+   if ( strImPos != GDCM_UNFOUND )
+   {
+      if ( sscanf( strImPos.c_str(), 
+          "%f \\%f \\%f ", &xImPos, &yImPos, &zImPos ) != 3 )
+      {
+         gdcmWarningMacro( "Wrong Image Position (RET) (0020,0030)");
+         return 0.;  // bug in the element 0x0020,0x0032
+      }
+      else
+      {
+         return zImPos;
+      }
+   }
+
+   // for *very* old ACR-NEMA images
+   std::string strSliceLocation = GetEntryValue(0x0020,0x1041);
+   if ( strSliceLocation != GDCM_UNFOUND )
+   {
+      if ( sscanf( strSliceLocation.c_str(), "%f ", &zImPos) != 1)
+      {
+         gdcmWarningMacro( "Wrong Slice Location (0020,1041)");
+         return 0.;  // bug in the element 0x0020,0x1041
+      }
+      else
+      {
+         return zImPos;
+      }
+   }
+   gdcmWarningMacro( "Unfound Slice Location (0020,1041)");
+
+   std::string strLocation = GetEntryValue(0x0020,0x0050);
+   if ( strLocation != GDCM_UNFOUND )
+   {
+      if ( sscanf( strLocation.c_str(), "%f ", &zImPos) != 1 )
+      {
+         gdcmWarningMacro( "Wrong Location (0020,0050)");
+         return 0.;  // bug in the element 0x0020,0x0050
+      }
+      else
+      {
+         return zImPos;
+      }
+   }
+   gdcmWarningMacro( "Unfound Location (0020,0050)");  
+
+   return 0.; // Hopeless
+}
+
+/**
+  * \brief gets the info from 0020,0037 : Image Orientation Patient
+  *                   or from 0020 0035 : Image Orientation (RET)
+  * (needed to organize DICOM files based on their x,y,z position)
+  * @param iop adress of the (6)float array to receive values
+  * @return true when one of the tag is found
+  *         false when nothing is found
+  */
+bool File::GetImageOrientationPatient( float iop[6] )
+{
+   std::string strImOriPat;
+   //iop is supposed to be float[6]
+   iop[0] = iop[4] = 1.;
+   iop[1] = iop[2] = iop[3] = iop[5] = 0.;
+
+   // 0020 0037 DS REL Image Orientation (Patient)
+   if ( (strImOriPat = GetEntryValue(0x0020,0x0037)) != GDCM_UNFOUND )
+   {
+      if ( sscanf( strImOriPat.c_str(), "%f \\ %f \\%f \\%f \\%f \\%f ", 
+          &iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6 )
+      {
+         gdcmWarningMacro( "Wrong Image Orientation Patient (0020,0037)."
+                        << " Less than 6 values were found." );
+         return false;
+      }
+      return true;
+   }
+   //For ACR-NEMA
+   // 0020 0035 DS REL Image Orientation (RET)
+   else if ( (strImOriPat = GetEntryValue(0x0020,0x0035)) != GDCM_UNFOUND )
+   {
+      if ( sscanf( strImOriPat.c_str(), "%f \\ %f \\%f \\%f \\%f \\%f ", 
+          &iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6 )
+      {
+         gdcmWarningMacro( "wrong Image Orientation Patient (0020,0035). "
+                        << "Less than 6 values were found." );
+         return false;
+      }
+      return true;
+   }
+   return false;
+}
+
+/**
+ * \brief   Retrieve the number of Bits Stored (actually used)
+ *          (as opposed to number of Bits Allocated)
+ * @return  The encountered number of Bits Stored, 0 by default.
+ *          0 means the file is NOT USABLE. The caller has to check it !
+ */
+int File::GetBitsStored()
+{
+   std::string strSize = GetEntryValue( 0x0028, 0x0101 );
+   if ( strSize == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro("BitsStored (0028,0101) is supposed to be mandatory");
+      return 0;
+   }
+   return atoi( strSize.c_str() );
+}
+
+/**
+ * \brief   Retrieve the number of Bits Allocated
+ *          (8, 12 -compacted ACR-NEMA files-, 16, 24 -old RGB ACR-NEMA files-,)
+ * @return  The encountered Number of Bits Allocated, 0 by default.
+ *          0 means the file is NOT USABLE. The caller has to check it !
+ */
+int File::GetBitsAllocated()
+{
+   std::string strSize = GetEntryValue(0x0028,0x0100);
+   if ( strSize == GDCM_UNFOUND  )
+   {
+      gdcmWarningMacro("BitsAllocated (0028,0100) is supposed to be mandatory");
+      return 0;
+   }
+   return atoi( strSize.c_str() );
+}
+
+/**
+ * \brief   Retrieve the high bit position.
+ * \warning The method defaults to 0 when information is missing.
+ *          The responsability of checking this value is left to the caller.
+ * @return  The high bit position when present. 0 when missing.
+ */
+int File::GetHighBitPosition()
+{
+   std::string strSize = GetEntryValue( 0x0028, 0x0102 );
+   if ( strSize == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro("HighBitPosition (0028,0102) is supposed to be mandatory");
+      return 0;
+   }
+   return atoi( strSize.c_str() );
+}
+
+/**
+ * \brief   Retrieve the number of Samples Per Pixel
+ *          (1 : gray level, 3 : RGB/YBR -1 or 3 Planes-)
+ * @return  The encountered number of Samples Per Pixel, 1 by default.
+ *          (we assume Gray level Pixels)
+ */
+int File::GetSamplesPerPixel()
+{
+   const std::string &strSize = GetEntryValue(0x0028,0x0002);
+   if ( strSize == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro("SamplesPerPixel (0028,0002) is supposed to be mandatory");
+      return 1; // Well, it's supposed to be mandatory ...
+                // but sometimes it's missing : *we* assume Gray pixels
+   }
+   return atoi( strSize.c_str() );
+}
+
+/**
+ * \brief   Retrieve the Planar Configuration for RGB images
+ *          (0 : RGB Pixels , 1 : R Plane + G Plane + B Plane)
+ * @return  The encountered Planar Configuration, 0 by default.
+ */
+int File::GetPlanarConfiguration()
+{
+   std::string strSize = GetEntryValue(0x0028,0x0006);
+   if ( strSize == GDCM_UNFOUND )
+   {
+      return 0;
+   }
+   return atoi( strSize.c_str() );
+}
+
+/**
+ * \brief   Return the size (in bytes) of a single pixel of data.
+ * @return  The size in bytes of a single pixel of data; 0 by default
+ *          0 means the file is NOT USABLE; the caller will have to check
+ */
+int File::GetPixelSize()
+{
+   // 0028 0100 US IMG Bits Allocated
+   // (in order no to be messed up by old ACR-NEMA RGB images)
+   assert( !(GetEntryValue(0x0028,0x0100) == "24") );
+
+   std::string pixelType = GetPixelType();
+   if ( pixelType ==  "8U" || pixelType == "8S" )
+   {
+      return 1;
+   }
+   if ( pixelType == "16U" || pixelType == "16S")
+   {
+      return 2;
+   }
+   if ( pixelType == "32U" || pixelType == "32S")
+   {
+      return 4;
+   }
+   if ( pixelType == "FD" )
+   {
+      return 8;
+   }
+   gdcmWarningMacro( "Unknown pixel type: " << pixelType);
+   return 0;
+}
+
+/**
+ * \brief   Build the Pixel Type of the image.
+ *          Possible values are:
+ *          - 8U  unsigned  8 bit,
+ *          - 8S    signed  8 bit,
+ *          - 16U unsigned 16 bit,
+ *          - 16S   signed 16 bit,
+ *          - 32U unsigned 32 bit,
+ *          - 32S   signed 32 bit,
+ *          - FD floating double 64 bits (Not kosher DICOM, but so usefull!)
+ * \warning 12 bit images appear as 16 bit.
+ *          24 bit images appear as 8 bit + photochromatic interp ="RGB "
+ *                                        + Planar Configuration = 0
+ * @return  0S if nothing found. NOT USABLE file. The caller has to check
+ */
+std::string File::GetPixelType()
+{
+   std::string bitsAlloc = GetEntryValue(0x0028, 0x0100); // Bits Allocated
+   if ( bitsAlloc == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro( "Bits Allocated (0028,0100) supposed to be mandatory");
+      bitsAlloc = "16"; // default and arbitrary value, not to polute the output
+   }
+
+   if ( bitsAlloc == "64" )
+   {
+      return "FD";
+   }
+   else if ( bitsAlloc == "12" )
+   {
+      // It will be unpacked
+      bitsAlloc = "16";
+   }
+   else if ( bitsAlloc == "24" )
+   {
+      // (in order no to be messed up by old RGB images)
+      bitsAlloc = "8";
+   }
+
+   std::string sign = GetEntryValue(0x0028, 0x0103);//"Pixel Representation"
+
+   if (sign == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro( "Missing Pixel Representation (0028,0103)");
+      sign = "U"; // default and arbitrary value, not to polute the output
+   }
+   else if ( sign == "0" )
+   {
+      sign = "U";
+   }
+   else
+   {
+      sign = "S";
+   }
+   return bitsAlloc + sign;
+}
+
+/**
+ * \brief   Check whether the pixels are signed (1) or UNsigned (0) data.
+ * \warning The method defaults to false (UNsigned) when tag 0028|0103
+ *          is missing.
+ *          The responsability of checking this value is left to the caller
+ *          (NO transformation is performed on the pixels to make then >0)
+ * @return  True when signed, false when UNsigned
+ */
+bool File::IsSignedPixelData()
+{
+   std::string strSign = GetEntryValue( 0x0028, 0x0103 );
+   if ( strSign == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro( "Pixel Representation (0028,0103) supposed to be "
+                      << "mandatory");
+      return false;
+   }
+   int sign = atoi( strSign.c_str() );
+   if ( sign == 0 ) 
+   {
+      return false;
+   }
+   return true;
+}
+
+/**
+ * \brief   Check whether this a monochrome picture (gray levels) or not,
+ *          using "Photometric Interpretation" tag (0x0028,0x0004).
+ * @return  true when "MONOCHROME1" or "MONOCHROME2". False otherwise.
+ */
+bool File::IsMonochrome()
+{
+   const std::string &PhotometricInterp = GetEntryValue( 0x0028, 0x0004 );
+   if (  Util::DicomStringEqual(PhotometricInterp, "MONOCHROME1")
+      || Util::DicomStringEqual(PhotometricInterp, "MONOCHROME2") )
+   {
+      return true;
+   }
+   if ( PhotometricInterp == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro( "Photometric Interpretation (0028,0004) supposed to be "
+                         << "mandatory");
+   }
+   return false;
+}
+
+/**
+ * \brief   Check whether this a MONOCHROME1 picture (high values = dark)
+ *            or not using "Photometric Interpretation" tag (0x0028,0x0004).
+ * @return  true when "MONOCHROME1" . False otherwise.
+ */
+bool File::IsMonochrome1()
+{
+   const std::string &PhotometricInterp = GetEntryValue( 0x0028, 0x0004 );
+   if (  Util::DicomStringEqual(PhotometricInterp, "MONOCHROME1") )
+   {
+      return true;
+   }
+   if ( PhotometricInterp == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro( "Photometric Interpretation (0028,0004) : supposed to"
+      << " be mandatory! ");
+   }
+   return false;
+}
+
+/**
+ * \brief   Check whether this a "PALETTE COLOR" picture or not by accessing
+ *          the "Photometric Interpretation" tag ( 0x0028, 0x0004 ).
+ * @return  true when "PALETTE COLOR". False otherwise.
+ */
+bool File::IsPaletteColor()
+{
+   std::string PhotometricInterp = GetEntryValue( 0x0028, 0x0004 );
+   if (   PhotometricInterp == "PALETTE COLOR " )
+   {
+      return true;
+   }
+   if ( PhotometricInterp == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro( "Not found : Palette color (0028,0004)");
+   }
+   return false;
+}
+
+/**
+ * \brief   Check whether this a "YBR_FULL" color picture or not by accessing
+ *          the "Photometric Interpretation" tag ( 0x0028, 0x0004 ).
+ * @return  true when "YBR_FULL". False otherwise.
+ */
+bool File::IsYBRFull()
+{
+   std::string PhotometricInterp = GetEntryValue( 0x0028, 0x0004 );
+   if (   PhotometricInterp == "YBR_FULL" )
+   {
+      return true;
+   }
+   if ( PhotometricInterp == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro( "Not found : YBR Full (0028,0004)");
+   }
+   return false;
+}
+
+/**
+  * \brief tells us if LUT are used
+  * \warning Right now, 'Segmented xxx Palette Color Lookup Table Data'
+  *          are NOT considered as LUT, since nobody knows
+  *          how to deal with them
+  *          Please warn me if you know sbdy that *does* know ... jprx
+  * @return true if LUT Descriptors and LUT Tables were found 
+  */
+bool File::HasLUT()
+{
+   // Check the presence of the LUT Descriptors, and LUT Tables    
+   // LutDescriptorRed    
+   if ( !GetDocEntry(0x0028,0x1101) )
+   {
+      return false;
+   }
+   // LutDescriptorGreen 
+   if ( !GetDocEntry(0x0028,0x1102) )
+   {
+      return false;
+   }
+   // LutDescriptorBlue 
+   if ( !GetDocEntry(0x0028,0x1103) )
+   {
+      return false;
+   }
+   // Red Palette Color Lookup Table Data
+   if ( !GetDocEntry(0x0028,0x1201) )
+   {
+      return false;
+   }
+   // Green Palette Color Lookup Table Data       
+   if ( !GetDocEntry(0x0028,0x1202) )
+   {
+      return false;
+   }
+   // Blue Palette Color Lookup Table Data      
+   if ( !GetDocEntry(0x0028,0x1203) )
+   {
+      return false;
+   }
+
+   // FIXME : (0x0028,0x3006) : LUT Data (CTX dependent)
+   //         NOT taken into account, but we don't know how to use it ...   
+   return true;
+}
+
+/**
+  * \brief gets the info from 0028,1101 : Lookup Table Desc-Red
+  *             else 0
+  * @return Lookup Table number of Bits , 0 by default
+  *          when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
+  * @ return bit number of each LUT item 
+  */
+int File::GetLUTNbits()
+{
+   std::vector<std::string> tokens;
+   int lutNbits;
+
+   //Just hope Lookup Table Desc-Red = Lookup Table Desc-Red
+   //                                = Lookup Table Desc-Blue
+   // Consistency already checked in GetLUTLength
+   std::string lutDescription = GetEntryValue(0x0028,0x1101);
+   if ( lutDescription == GDCM_UNFOUND )
+   {
+      return 0;
+   }
+
+   tokens.clear(); // clean any previous value
+   Util::Tokenize ( lutDescription, tokens, "\\" );
+   //LutLength=atoi(tokens[0].c_str());
+   //LutDepth=atoi(tokens[1].c_str());
+
+   lutNbits = atoi( tokens[2].c_str() );
+   tokens.clear();
+
+   return lutNbits;
+}
+
+/**
+ *\brief gets the info from 0028,1052 : Rescale Intercept
+ * @return Rescale Intercept
+ */
+float File::GetRescaleIntercept()
+{
+   float resInter = 0.;
+   /// 0028 1052 DS IMG Rescale Intercept
+   const std::string &strRescInter = GetEntryValue(0x0028,0x1052);
+   if ( strRescInter != GDCM_UNFOUND )
+   {
+      if ( sscanf( strRescInter.c_str(), "%f ", &resInter) != 1 )
+      {
+         // bug in the element 0x0028,0x1052
+         gdcmWarningMacro( "Rescale Intercept (0028,1052) is empty." );
+      }
+   }
+
+   return resInter;
+}
+
+/**
+ *\brief   gets the info from 0028,1053 : Rescale Slope
+ * @return Rescale Slope. defaulted to 1.0 is not found or empty
+ */
+float File::GetRescaleSlope()
+{
+   float resSlope = 1.;
+   //0028 1053 DS IMG Rescale Slope
+   std::string strRescSlope = GetEntryValue(0x0028,0x1053);
+   if ( strRescSlope != GDCM_UNFOUND )
+   {
+      if ( sscanf( strRescSlope.c_str(), "%f ", &resSlope) != 1 )
+      {
+         // bug in the element 0x0028,0x1053
+         gdcmWarningMacro( "Rescale Slope (0028,1053) is empty.");
+      }
+   }
+
+   return resSlope;
+}
+
+/**
+ * \brief This function is intended to user who doesn't want 
+ *   to have to manage a LUT and expects to get an RBG Pixel image
+ *   (or a monochrome one ...) 
+ * \warning to be used with GetImagePixels()
+ * @return 1 if Gray level, 3 if Color (RGB, YBR, *or PALETTE COLOR*)
+ */
+int File::GetNumberOfScalarComponents()
+{
+   if ( GetSamplesPerPixel() == 3 )
+   {
+      return 3;
+   }
+
+   // 0028 0100 US IMG Bits Allocated
+   // (in order no to be messed up by old RGB images)
+   if ( GetEntryValue(0x0028,0x0100) == "24" )
+   {
+      return 3;
+   }
+
+   std::string strPhotometricInterpretation = GetEntryValue(0x0028,0x0004);
+
+   if ( ( strPhotometricInterpretation == "PALETTE COLOR ") )
+   {
+      if ( HasLUT() )// PALETTE COLOR is NOT enough
+      {
+         return 3;
+      }
+      else
+      {
+         return 1;
+      }
+   }
+
+   // beware of trailing space at end of string      
+   // DICOM tags are never of odd length
+   if ( strPhotometricInterpretation == GDCM_UNFOUND   || 
+        Util::DicomStringEqual(strPhotometricInterpretation, "MONOCHROME1") ||
+        Util::DicomStringEqual(strPhotometricInterpretation, "MONOCHROME2") )
+   {
+      return 1;
+   }
+   else
+   {
+      // we assume that *all* kinds of YBR are dealt with
+      return 3;
+   }
+}
+
+/**
+ * \brief This function is intended to user that DOESN'T want 
+ *  to get RGB pixels image when it's stored as a PALETTE COLOR image
+ *   - the (vtk) user is supposed to know how deal with LUTs - 
+ * \warning to be used with GetImagePixelsRaw()
+ * @return 1 if Gray level, 3 if Color (RGB or YBR - NOT 'PALETTE COLOR' -)
+ */
+int File::GetNumberOfScalarComponentsRaw()
+{
+   // 0028 0100 US IMG Bits Allocated
+   // (in order no to be messed up by old RGB images)
+   if ( File::GetEntryValue(0x0028,0x0100) == "24" )
+   {
+      return 3;
+   }
+
+   // we assume that *all* kinds of YBR are dealt with
+   return GetSamplesPerPixel();
+}
+
+/**
+ * \brief   Recover the offset (from the beginning of the file) 
+ *          of *image* pixels (not *icone image* pixels, if any !)
+ * @return Pixel Offset
+ */
+size_t File::GetPixelOffset()
+{
+   DocEntry *pxlElement = GetDocEntry(GrPixel, NumPixel);
+   if ( pxlElement )
+   {
+      return pxlElement->GetOffset();
+   }
+   else
+   {
+      gdcmDebugMacro( "Big trouble : Pixel Element ("
+                      << std::hex << GrPixel<<","<< NumPixel<< ") NOT found" );
+      return 0;
+   }
+}
+
+/**
+ * \brief   Recover the pixel area length (in Bytes)
+ * @return Pixel Element Length, as stored in the header
+ *         (NOT the memory space necessary to hold the Pixels 
+ *          -in case of embeded compressed image-)
+ *         0 : NOT USABLE file. The caller has to check.
+ */
+size_t File::GetPixelAreaLength()
+{
+   DocEntry *pxlElement = GetDocEntry(GrPixel, NumPixel);
+   if ( pxlElement )
+   {
+      return pxlElement->GetLength();
+   }
+   else
+   {
+      gdcmDebugMacro( "Big trouble : Pixel Element ("
+                      << std::hex << GrPixel<<","<< NumPixel<< ") NOT found" );
+      return 0;
+   }
+}
+
+/**
+ * \brief Adds the characteristics of a new element we want to anonymize
+ * @param   group  Group number of the target tag.
+ * @param   elem Element number of the target tag.
+ * @param   value new value (string) to substitute with 
+ */
+void File::AddAnonymizeElement (uint16_t group, uint16_t elem, 
+                                std::string const &value) 
+{ 
+   Element el;
+   el.Group = group;
+   el.Elem  = elem;
+   el.Value = value;
+   UserAnonymizeList.push_back(el); 
+}
+
+/**
+ * \brief Overwrites in the file the values of the DicomElements
+ *       held in the list 
+ */
+void File::AnonymizeNoLoad()
+{
+   std::fstream *fp = new std::fstream(Filename.c_str(), 
+                              std::ios::in | std::ios::out | std::ios::binary); 
+   gdcm::DocEntry *d;
+   uint32_t offset;
+   uint32_t lgth;
+   uint32_t valLgth = 0;
+   std::string *spaces;
+   for (ListElements::iterator it = UserAnonymizeList.begin();  
+                               it != UserAnonymizeList.end();
+                             ++it)
+   { 
+      d = GetDocEntry( (*it).Group, (*it).Elem);
+
+      if ( d == NULL)
+         continue;
+
+      if ( dynamic_cast<SeqEntry *>(d) )
+      {
+         gdcmWarningMacro( "You cannot 'Anonymize' a SeqEntry ");
+         continue;
+      }
+
+      offset = d->GetOffset();
+      lgth =   d->GetLength();
+      if (valLgth < lgth)
+      {
+         spaces = new std::string( lgth-valLgth, ' ');
+         (*it).Value = (*it).Value + *spaces;
+         delete spaces;
+      }
+      fp->seekp( offset, std::ios::beg );
+      fp->write( (*it).Value.c_str(), lgth );
+     
+   }
+   fp->close();
+   delete fp;
+}
+
+/**
+ * \brief anonymize a File (remove Patient's personal info passed with
+ *        AddAnonymizeElement()
+ * \note You cannot Anonymize a BinEntry (to be fixed)
+ */
+bool File::AnonymizeFile()
+{
+   // If Anonymisation list is empty, let's perform some basic anonymization
+   if ( UserAnonymizeList.begin() == UserAnonymizeList.end() )
+   {
+      // If exist, replace by spaces
+      SetValEntry ("  ",0x0010, 0x2154); // Telephone   
+      SetValEntry ("  ",0x0010, 0x1040); // Adress
+      SetValEntry ("  ",0x0010, 0x0020); // Patient ID
+
+      DocEntry* patientNameHE = GetDocEntry (0x0010, 0x0010);
+  
+      if ( patientNameHE ) // we replace it by Study Instance UID (why not ?)
+      {
+         std::string studyInstanceUID =  GetEntryValue (0x0020, 0x000d);
+         if ( studyInstanceUID != GDCM_UNFOUND )
+         {
+            SetValEntry(studyInstanceUID, 0x0010, 0x0010);
+         }
+         else
+         {
+            SetValEntry("anonymized", 0x0010, 0x0010);
+         }
+      }
+   }
+   else
+   {
+      gdcm::DocEntry *d;
+      for (ListElements::iterator it = UserAnonymizeList.begin();  
+                                  it != UserAnonymizeList.end();
+                                ++it)
+      {  
+         d = GetDocEntry( (*it).Group, (*it).Elem);
+
+         if ( d == NULL)
+            continue;
+
+         if ( dynamic_cast<SeqEntry *>(d) )
+         {
+            gdcmWarningMacro( "You cannot 'Anonymize' a SeqEntry ");
+            continue;
+         }
+
+         if ( dynamic_cast<BinEntry *>(d) )
+         {
+            gdcmWarningMacro( "To 'Anonymize' a BinEntry, better use AnonymizeNoLoad (FIXME) ");
+            continue;
+         }
+         else
+            SetValEntry ((*it).Value, (*it).Group, (*it).Elem);
+      }
+}
+
+  // In order to make definitively impossible any further identification
+  // remove or replace all the stuff that contains a Date
+
+//0008 0012 DA ID Instance Creation Date
+//0008 0020 DA ID Study Date
+//0008 0021 DA ID Series Date
+//0008 0022 DA ID Acquisition Date
+//0008 0023 DA ID Content Date
+//0008 0024 DA ID Overlay Date
+//0008 0025 DA ID Curve Date
+//0008 002a DT ID Acquisition Datetime
+//0018 9074 DT ACQ Frame Acquisition Datetime
+//0018 9151 DT ACQ Frame Reference Datetime
+//0018 a002 DT ACQ Contribution Date Time
+//0020 3403 SH REL Modified Image Date (RET)
+//0032 0032 DA SDY Study Verified Date
+//0032 0034 DA SDY Study Read Date
+//0032 1000 DA SDY Scheduled Study Start Date
+//0032 1010 DA SDY Scheduled Study Stop Date
+//0032 1040 DA SDY Study Arrival Date
+//0032 1050 DA SDY Study Completion Date
+//0038 001a DA VIS Scheduled Admission Date
+//0038 001c DA VIS Scheduled Discharge Date
+//0038 0020 DA VIS Admitting Date
+//0038 0030 DA VIS Discharge Date
+//0040 0002 DA PRC Scheduled Procedure Step Start Date
+//0040 0004 DA PRC Scheduled Procedure Step End Date
+//0040 0244 DA PRC Performed Procedure Step Start Date
+//0040 0250 DA PRC Performed Procedure Step End Date
+//0040 2004 DA PRC Issue Date of Imaging Service Request
+//0040 4005 DT PRC Scheduled Procedure Step Start Date and Time
+//0040 4011 DT PRC Expected Completion Date and Time
+//0040 a030 DT PRC Verification Date Time
+//0040 a032 DT PRC Observation Date Time
+//0040 a120 DT PRC DateTime
+//0040 a121 DA PRC Date
+//0040 a13a DT PRC Referenced Datetime
+//0070 0082 DA ??? Presentation Creation Date
+//0100 0420 DT ??? SOP Autorization Date and Time
+//0400 0105 DT ??? Digital Signature DateTime
+//2100 0040 DA PJ Creation Date
+//3006 0008 DA SSET Structure Set Date
+//3008 0024 DA ??? Treatment Control Point Date
+//3008 0054 DA ??? First Treatment Date
+//3008 0056 DA ??? Most Recent Treatment Date
+//3008 0162 DA ??? Safe Position Exit Date
+//3008 0166 DA ??? Safe Position Return Date
+//3008 0250 DA ??? Treatment Date
+//300a 0006 DA RT RT Plan Date
+//300a 022c DA RT Air Kerma Rate Reference Date
+//300e 0004 DA RT Review Date
+
+   return true;
+}
+
+/**
+ * \brief Performs some consistency checking on various 'File related' 
+ *       (as opposed to 'DicomDir related') entries 
+ *       then writes in a file all the (Dicom Elements) included the Pixels 
+ * @param fileName file name to write to
+ * @param writetype type of the file to be written 
+ *          (ACR, ExplicitVR, ImplicitVR)
+ */
+bool File::Write(std::string fileName, FileType writetype)
+{
+   std::ofstream *fp = new std::ofstream(fileName.c_str(), 
+                                         std::ios::out | std::ios::binary);
+   if (*fp == NULL)
+   {
+      gdcmWarningMacro("Failed to open (write) File: " << fileName.c_str());
+      return false;
+   }
+
+   // Entry : 0002|0000 = group length -> recalculated
+   ValEntry *e0000 = GetValEntry(0x0002,0x0000);
+   if ( e0000 )
+   {
+      itksys_ios::ostringstream sLen;
+      sLen << ComputeGroup0002Length( );
+      e0000->SetValue(sLen.str());
+   }
+
+   int i_lgPix = GetEntryLength(GrPixel, NumPixel);
+   if (i_lgPix != -2)
+   {
+      // no (GrPixel, NumPixel) element
+      std::string s_lgPix = Util::Format("%d", i_lgPix+12);
+      s_lgPix = Util::DicomString( s_lgPix.c_str() );
+      InsertValEntry(s_lgPix,GrPixel, 0x0000);
+   }
+   Document::WriteContent(fp, writetype);
+
+   fp->close();
+   delete fp;
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \brief Parse pixel data from disk of [multi-]fragment RLE encoding.
+ *        Compute the RLE extra information and store it in \ref RLEInfo
+ *        for later pixel retrieval usage.
+ */
+void File::ComputeRLEInfo()
+{
+   std::string ts = GetTransferSyntax();
+   if ( !Global::GetTS()->IsRLELossless(ts) ) 
+   {
+      return;
+   }
+
+   // Encoded pixel data: for the time being we are only concerned with
+   // Jpeg or RLE Pixel data encodings.
+   // As stated in PS 3.5-2003, section 8.2 p44:
+   // "If sent in Encapsulated Format (i.e. other than the Native Format) the
+   //  value representation OB is used".
+   // Hence we expect an OB value representation. Concerning OB VR,
+   // the section PS 3.5-2003, section A.4.c p 58-59, states:
+   // "For the Value Representations OB and OW, the encoding shall meet the
+   //   following specifications depending on the Data element tag:"
+   //   [...snip...]
+   //    - the first item in the sequence of items before the encoded pixel
+   //      data stream shall be basic offset table item. The basic offset table
+   //      item value, however, is not required to be present"
+   ReadEncapsulatedBasicOffsetTable();
+
+   // Encapsulated RLE Compressed Images (see PS 3.5-2003, Annex G)
+   // Loop on the individual frame[s] and store the information
+   // on the RLE fragments in a RLEFramesInfo.
+   // Note: - when only a single frame is present, this is a
+   //         classical image.
+   //       - when more than one frame are present, then we are in 
+   //         the case of a multi-frame image.
+   long frameLength;
+   int i=0;
+   uint32_t sum = 0;
+   while ( (frameLength = ReadTagLength(0xfffe, 0xe000)) != 0 )
+   { 
+      // Since we have read the basic offset table, let's check the value were correct
+      // or else produce a warning:
+      if ( BasicOffsetTableItemValue )
+        {
+        // If a BasicOffsetTableItemValue was read
+        uint32_t individualLength = BasicOffsetTableItemValue[i];
+        assert( individualLength == sum ); // REMOVE that if this is a problem
+        if( individualLength != sum )
+          {
+          gdcmWarningMacro( "BasicOffsetTableItemValue differs from the fragment lenght" );
+          }
+        sum += frameLength + 8;
+        i++;
+        }
+      // Parse the RLE Header and store the corresponding RLE Segment
+      // Offset Table information on fragments of this current Frame.
+      // Note that the fragment pixels themselves are not loaded
+      // (but just skipped).
+      long frameOffset = Fp->tellg(); // once per fragment
+
+      uint32_t nbRleSegments = ReadInt32();
+      if ( nbRleSegments > 16 )
+      {
+         // There should be at most 15 segments (refer to RLEFrame class)
+         gdcmWarningMacro( "Too many segments.");
+      }
+ 
+      uint32_t rleSegmentOffsetTable[16];
+      for( int k = 1; k <= 15; k++ )
+      {
+         rleSegmentOffsetTable[k] = ReadInt32();
+      }
+
+      // Deduce from both RLE Header and frameLength 
+      // the fragment length, and again store this info
+      // in a RLEFramesInfo.
+      long rleSegmentLength[15];
+      // skipping (not reading) RLE Segments
+      if ( nbRleSegments > 1)
+      {
+         for(unsigned int k = 1; k <= nbRleSegments-1; k++)
+         {
+             rleSegmentLength[k] =  rleSegmentOffsetTable[k+1]
+                                  - rleSegmentOffsetTable[k];
+             SkipBytes(rleSegmentLength[k]);
+          }
+       }
+
+       rleSegmentLength[nbRleSegments] = frameLength 
+                                      - rleSegmentOffsetTable[nbRleSegments];
+       SkipBytes(rleSegmentLength[nbRleSegments]);
+
+       // Store the collected info
+       RLEFrame *newFrame = new RLEFrame;
+       newFrame->SetNumberOfFragments(nbRleSegments);
+       for( unsigned int uk = 1; uk <= nbRleSegments; uk++ )
+       {
+          newFrame->SetOffset(uk,frameOffset + rleSegmentOffsetTable[uk]);
+          newFrame->SetLength(uk,rleSegmentLength[uk]);
+       }
+       RLEInfo->AddFrame(newFrame);
+   }
+
+   // Make sure that  we encounter a 'Sequence Delimiter Item'
+   // at the end of the item :
+   if ( !ReadTag(0xfffe, 0xe0dd) ) // once per RLE File
+   {
+      gdcmWarningMacro( "No sequence delimiter item at end of RLE item sequence");
+   }
+}
+
+/**
+ * \brief Parse pixel data from disk of [multi-]fragment Jpeg encoding.
+ *        Compute the jpeg extra information (fragment[s] offset[s] and
+ *        length) and store it[them] in \ref JPEGInfo for later pixel
+ *        retrieval usage.
+ */
+void File::ComputeJPEGFragmentInfo()
+{
+   // If you need to, look for comments of ComputeRLEInfo().
+   std::string ts = GetTransferSyntax();
+   if ( ! Global::GetTS()->IsJPEG(ts) )
+   {
+      return;
+   }
+
+   ReadEncapsulatedBasicOffsetTable();
+
+   // Loop on the fragments[s] and store the parsed information in a
+   // JPEGInfo.
+   long fragmentLength;
+   int i=0;
+   uint32_t sum = 0;
+   while ( (fragmentLength = ReadTagLength(0xfffe, 0xe000)) != 0 )
+   { 
+      // Since we have read the basic offset table, let's check the value were correct
+      // or else produce a warning:
+      // A.4 Transfer syntaxes for encapsulation of encoded pixel data:
+      // When the Item Value is present, the Basic Offset Table Item Value shall contain
+      // concatenated 32-bit unsigned integer values that are byte offsets to the first
+      // byte of the Item Tag of the first fragment for each frame in the Sequence of
+      // Items. These offsets are measured from the first byte of the first Item Tag
+      // following the Basic Offset Table item (See Table A.4-2).
+
+      if ( BasicOffsetTableItemValue )
+        {
+        // If a BasicOffsetTableItemValue was read
+        uint32_t individualLength = BasicOffsetTableItemValue[i];
+        //assert( individualLength == sum ); // Seems like 00191113.dcm is off by one ??
+        if( individualLength != sum )
+          {
+          gdcmWarningMacro( "BasicOffsetTableItemValue differs from the fragment lenght:" <<
+              individualLength << " != " << sum );
+          }
+        sum += fragmentLength + 8;
+        i++;
+        }
+
+      long fragmentOffset = Fp->tellg(); // Once per fragment
+      // Store the collected info
+      JPEGFragment *newFragment = new JPEGFragment;
+      newFragment->SetOffset(fragmentOffset);
+      newFragment->SetLength(fragmentLength);
+      JPEGInfo->AddFragment(newFragment);
+
+      SkipBytes(fragmentLength);
+   }
+
+   // Make sure that  we encounter a 'Sequence Delimiter Item'
+   // at the end of the item :
+   if ( !ReadTag(0xfffe, 0xe0dd) )
+   {
+      gdcmWarningMacro( "No sequence delimiter item at end of JPEG item sequence");
+   }
+}
+
+/**
+ * \brief   Assuming the internal file pointer \ref Document::Fp 
+ *          is placed at the beginning of a tag, check whether this
+ *          tag is (TestGroup, TestElem).
+ * \warning On success the internal file pointer \ref Document::Fp
+ *          is modified to point after the tag.
+ *          On failure (i.e. when the tag wasn't the expected tag
+ *          (TestGroup, TestElem) the internal file pointer
+ *          \ref Document::Fp is restored to it's original position.
+ * @param   testGroup The expected group   of the tag.
+ * @param   testElem  The expected Element of the tag.
+ * @return  True on success, false otherwise.
+ */
+bool File::ReadTag(uint16_t testGroup, uint16_t testElem)
+{
+   long positionOnEntry = Fp->tellg(); // Only when reading fragments
+   //long currentPosition = positionOnEntry;      // On debugging purposes
+
+   // Read the Item Tag group and element, and make
+   // sure they are what we expected:
+   uint16_t itemTagGroup;
+   uint16_t itemTagElem;
+   try
+   {
+      itemTagGroup = ReadInt16();
+      itemTagElem  = ReadInt16();
+   }
+   catch ( FormatError )
+   {
+      gdcmErrorMacro( "Can not read tag for "
+       << "   We should have found tag ("
+       << DictEntry::TranslateToKey(testGroup,testElem) << ")"
+       ) ;
+
+      return false;
+   }
+   if ( itemTagGroup != testGroup || itemTagElem != testElem )
+   {
+       // in order not to pollute output we don't warn on 'delimitors'
+      if (itemTagGroup != 0xfffe ||  testGroup != 0xfffe )
+      gdcmWarningMacro( "Wrong Item Tag found:"
+       << "   We should have found tag ("
+       << std::hex << testGroup << "," << testElem << ")" << std::endl
+       << "   but instead we encountered tag ("
+       << std::hex << itemTagGroup << "," << itemTagElem << ")"
+       << "  at address: " << "  0x(" << (unsigned int)positionOnEntry << ")" 
+       ) ;
+      Fp->seekg(positionOnEntry, std::ios::beg);
+
+      return false;
+   }
+   return true;
+}
+
+/**
+ * \brief   Assuming the internal file pointer \ref Document::Fp 
+ *          is placed at the beginning of a tag (TestGroup, TestElement),
+ *          read the length associated to the Tag.
+ * \warning On success the internal file pointer \ref Document::Fp
+ *          is modified to point after the tag and it's length.
+ *          On failure (i.e. when the tag wasn't the expected tag
+ *          (TestGroup, TestElement) the internal file pointer
+ *          \ref Document::Fp is restored to it's original position.
+ * @param   testGroup The expected Group   of the tag.
+ * @param   testElem  The expected Element of the tag.
+ * @return  On success returns the length associated to the tag. On failure
+ *          returns 0.
+ */
+uint32_t File::ReadTagLength(uint16_t testGroup, uint16_t testElem)
+{
+
+   if ( !ReadTag(testGroup, testElem) )
+   {
+      return 0;
+   }
+                                                                                
+   //// Then read the associated Item Length
+   long currentPosition = Fp->tellg();
+   uint32_t itemLength  = ReadInt32();
+   {
+      gdcmWarningMacro( "Basic Item Length is: "
+        << itemLength << std::endl
+        << "  at address: " << std::hex << (unsigned int)currentPosition);
+   }
+   return itemLength;
+}
+
+/**
+ * \brief When parsing the Pixel Data of an encapsulated file, read
+ *        the basic offset table (when present, and BTW dump it).
+ */
+void File::ReadEncapsulatedBasicOffsetTable()
+{
+   //// Read the Basic Offset Table Item Tag length...
+   uint32_t itemLength = ReadTagLength(0xfffe, 0xe000);
+
+   // When present, read the basic offset table itself.
+   // Notes: - since the presence of this basic offset table is optional
+   //          we can't rely on it for the implementation, and we will simply
+   //          trash it's content (when present).
+   //        - still, when present, we could add some further checks on the
+   //          lengths, but we won't bother with such fuses for the time being.
+   if ( itemLength != 0 )
+   {
+      char *charBasicOffsetTableItemValue = new char[itemLength];
+      Fp->read(charBasicOffsetTableItemValue, itemLength);
+      unsigned int nbEntries = itemLength/4;
+      assert( nbEntries*4 == itemLength); // Make sure this is a multiple
+      BasicOffsetTableItemValue = new uint32_t[nbEntries];
+
+      for (unsigned int i=0; i < nbEntries; i++ )
+      {
+         BasicOffsetTableItemValue[i] = *((uint32_t*)(&charBasicOffsetTableItemValue[4*i]));
+#if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)
+         uint32_t val = BasicOffsetTableItemValue[i];
+         BasicOffsetTableItemValue[i] 
+           = (  (val<<24)               | ((val<<8)  & 0x00ff0000) | 
+              ( (val>>8)  & 0x0000ff00) |  (val>>24)               );
+#endif
+         gdcmDebugMacro( "Read one length for: " << 
+                          std::hex << BasicOffsetTableItemValue[i] );
+      }
+
+      delete[] charBasicOffsetTableItemValue;
+   }
+}
+
+// These are the deprecated method that one day should be removed (after the next release)
+
+#ifndef GDCM_LEGACY_REMOVE
+/*
+ * \brief  Constructor (DEPRECATED : temporaryly kept not to break the API)
+ * @param  filename name of the file whose header we want to analyze
+ * @deprecated do not use any longer
+ */
+File::File( std::string const &filename )
+     :Document( )
+{    
+   RLEInfo  = new RLEFramesInfo;
+   JPEGInfo = new JPEGFragmentsInfo;
+   GrPixel  = 0x7fe0;  // to avoid further troubles
+   NumPixel = 0x0010;
+   BasicOffsetTableItemValue = 0;
+
+   SetFileName( filename );
+   Load( ); // gdcm::Document is first Loaded, then the 'File part'
+}
+
+/**
+ * \brief   Loader. (DEPRECATED :  temporaryly kept not to break the API)
+ * @param   fileName file to be open for parsing
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
+ * @deprecated Use the Load() [ + SetLoadMode() ] + SetFileName() functions instead
+ */
+bool File::Load( std::string const &fileName ) 
+{
+   GDCM_LEGACY_REPLACED_BODY(File::Load(std::string), "1.2",
+                             File::Load());
+   SetFileName( fileName );
+   if ( ! this->Document::Load( ) )
+      return false;
+
+   return DoTheLoadingJob( );
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Print
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmFile.h b/Utilities/ITK/Utilities/gdcm/src/gdcmFile.h
new file mode 100644
index 0000000000000000000000000000000000000000..b07e0629f000bb0d7037b76fec96ec1918e0832c
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmFile.h
@@ -0,0 +1,208 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmFile.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.5 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMFILE_H
+#define GDCMFILE_H
+
+#include "gdcmDebug.h"
+#include "gdcmDocument.h"
+
+
+
+namespace gdcm 
+{
+
+class RLEFramesInfo;
+class JPEGFragmentsInfo;
+
+//-----------------------------------------------------------------------------
+// Dicom Part 3.3 Compliant
+enum ModalityType {
+   Unknow,
+   AU,       // Voice Audio
+   AS,       // Angioscopy
+   BI,       // Biomagnetic Imaging
+   CF,       // Cinefluorography
+   CP,       // Culposcopy
+   CR,       // Computed Radiography
+   CS,       // Cystoscopy
+   CT,       // Computed Tomography
+   DD,       // Duplex Dopler
+   DF,       // Digital Fluoroscopy
+   DG,       // Diaphanography
+   DM,       // Digital Microscopy
+   DS,       // Digital Substraction Angiography
+   DX,       // Digital Radiography
+   ECG,      // Echocardiography
+   EPS,      // Basic Cardiac EP
+   ES,       // Endoscopy
+   FA,       // Fluorescein Angiography
+   FS,       // Fundoscopy
+   HC,       // Hard Copy
+   HD,       // Hemodynamic
+   LP,       // Laparoscopy
+   LS,       // Laser Surface Scan
+   MA,       // Magnetic Resonance Angiography
+   MR,       // Magnetic Resonance
+   NM,       // Nuclear Medicine
+   OT,       // Other
+   PT,       // Positron Emission Tomography
+   RF,       // Radio Fluoroscopy
+   RG,       // Radiographic Imaging
+   RTDOSE,   // Radiotherapy Dose
+   RTIMAGE,  // Radiotherapy Image
+   RTPLAN,   // Radiotherapy Plan
+   RTSTRUCT, // Radiotherapy Structure Set
+   SM,       // Microscopic Imaging
+   ST,       // Single-photon Emission Computed Tomography
+   TG,       // Thermography
+   US,       // Ultrasound
+   VF,       // Videofluorography
+   XA,       // X-Ray Angiography
+   XC        // Photographic Imaging
+};
+
+//-----------------------------------------------------------------------------
+
+/**
+ * \brief DICOM elements and their corresponding values (and
+ * additionaly the corresponding DICOM dictionary entry) of the header
+ * of a DICOM file.
+ *
+ * The typical usage of instances of class File is to classify a set of
+ * dicom files according to header information e.g. to create a file hierarchy
+ * reflecting the Patient/Study/Serie informations, or extracting a given
+ * SerieId. Accessing the content (image[s] or volume[s]) is beyond the
+ * functionality of this class and belongs to gdcm::FileHelper.
+ * \note  The various entries of the explicit value representation (VR) shall
+ *        be managed within a dictionary which is shared by all File
+ *        instances.
+ * \note  The File::Set*Tag* family members cannot be defined as
+ *        protected due to Swig limitations for as Has_a dependency between
+ *        File and FileHelper.
+ */
+class GDCM_EXPORT File : public Document
+{
+public:
+   File();
+   GDCM_LEGACY(File( std::string const &filename ));
+   ~File();
+
+   // Loading
+   GDCM_LEGACY(bool Load( std::string const &filename ));
+   bool Load(); 
+   // Standard values and informations contained in the header
+   bool IsReadable();
+
+   // Some heuristic based accessors, end user intended 
+   int GetImageNumber();
+   ModalityType GetModality();
+
+   int GetXSize();
+   int GetYSize();
+   int GetZSize();
+
+   float GetXSpacing();
+   float GetYSpacing();
+   float GetZSpacing();
+
+   float GetXOrigin();
+   float GetYOrigin();
+   float GetZOrigin();
+
+   bool GetImageOrientationPatient( float iop[6] );
+
+   int GetBitsStored();
+   int GetBitsAllocated();
+   int GetHighBitPosition();
+   int GetSamplesPerPixel();
+   int GetPlanarConfiguration();
+   int GetPixelSize();
+   std::string GetPixelType();
+   bool IsSignedPixelData();
+   bool IsMonochrome();
+   bool IsMonochrome1();
+   bool IsPaletteColor();
+   bool IsYBRFull();
+
+   bool HasLUT();
+   int GetLUTNbits();
+
+   // For rescaling graylevel:
+   float GetRescaleIntercept();
+   float GetRescaleSlope();
+
+   int GetNumberOfScalarComponents();
+   int GetNumberOfScalarComponentsRaw();
+
+   /// Accessor to \ref File::GrPixel
+   uint16_t GetGrPixel()  { return GrPixel; }
+   /// Accessor to \ref File::NumPixel
+   uint16_t GetNumPixel() { return NumPixel; }
+
+   size_t GetPixelOffset();
+   size_t GetPixelAreaLength();
+
+   /// returns the RLE info
+   RLEFramesInfo *GetRLEInfo() { return RLEInfo; }
+   /// Returns the JPEG Fragments info
+   JPEGFragmentsInfo *GetJPEGInfo() { return JPEGInfo; }
+
+// Anonymization process
+   void AddAnonymizeElement (uint16_t group, uint16_t elem, 
+                             std::string const &value);
+   /// Clears the list of elements to be anonymized
+   void ClearAnonymizeList() { UserAnonymizeList.clear(); }      
+   void AnonymizeNoLoad();
+   /// Replace patient's own information by info from the Anonymization list
+   bool AnonymizeFile();
+
+   bool Write(std::string fileName, FileType filetype);
+
+protected:
+ 
+   /// Store the RLE frames info obtained during parsing of pixels.
+   RLEFramesInfo *RLEInfo;
+   /// Store the JPEG fragments info obtained during parsing of pixels.
+   JPEGFragmentsInfo *JPEGInfo;
+
+   /// \brief In some cases (e.g. for some ACR-NEMA images) the Entry Element
+   /// Number of the 'Pixel Element' is *not* found at 0x0010. In order to
+   /// make things easier the parser shall store the proper value in
+   /// NumPixel to provide a unique access facility. 
+   uint16_t NumPixel;
+   /// \brief In some cases (e.g. for some ACR-NEMA images) the header entry for
+   /// the group of pixels is *not* found at 0x7fe0. 
+   /// In order to make things easier the parser shall store the proper value
+   /// in GrPixel to provide a unique access facility.
+   uint16_t GrPixel;
+
+private:
+   bool DoTheLoadingJob();
+   void ComputeRLEInfo();
+   void ComputeJPEGFragmentInfo();
+   bool     ReadTag(uint16_t, uint16_t);
+   uint32_t ReadTagLength(uint16_t, uint16_t);
+   void ReadEncapsulatedBasicOffsetTable();
+   uint32_t *BasicOffsetTableItemValue;
+
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmFileHelper.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmFileHelper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a6f7a08c24989af71b6e038ffa307f0dddefa211
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmFileHelper.cxx
@@ -0,0 +1,1763 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmFileHelper.cxx,v $
+  Language:  C++
+
+  Date:      $Date: 2006/03/08 20:09:44 $
+  Version:   $Revision: 1.12 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmFileHelper.h"
+#include "gdcmGlobal.h"
+#include "gdcmTS.h"
+#include "gdcmDocument.h"
+#include "gdcmDebug.h"
+#include "gdcmUtil.h"
+#include "gdcmBinEntry.h"
+#include "gdcmValEntry.h"
+#include "gdcmSeqEntry.h"
+#include "gdcmSQItem.h"
+#include "gdcmContentEntry.h"
+#include "gdcmFile.h"
+#include "gdcmPixelReadConvert.h"
+#include "gdcmPixelWriteConvert.h"
+#include "gdcmDocEntryArchive.h"
+#include "gdcmDictSet.h"
+#include "gdcmOrientation.h"
+#if defined(__BORLANDC__)
+   #include <mem.h> // for memset
+#endif 
+
+#include <fstream>
+
+/*
+// ----------------------------- WARNING -------------------------
+
+These lines will be moved to the document-to-be 'User's Guide'
+
+// To read an image, user needs a gdcm::File
+gdcm::File *f = new gdcm::File(fileName);
+// or (advanced) :
+// user may also decide he doesn't want to load some parts of the header
+gdcm::File *f = new gdcm::File();
+f->SetFileName(fileName);
+   f->SetLoadMode(LD_NOSEQ);             // or      
+   f->SetLoadMode(LD_NOSHADOW);          // or
+   f->SetLoadMode(LD_NOSEQ | LD_NOSHADOW); // or
+   f->SetLoadMode(LD_NOSHADOWSEQ);
+f->Load();
+
+// user can now check some values
+std::string v = f->GetEntryValue(groupNb,ElementNb);
+
+// to get the pixels, user needs a gdcm::FileHelper
+gdcm::FileHelper *fh = new gdcm::FileHelper(f);
+// user may ask not to convert Palette to RGB
+uint8_t *pixels = fh->GetImageDataRaw();
+int imageLength = fh->GetImageDataRawSize();
+// He can now use the pixels, create a new image, ...
+uint8_t *userPixels = ...
+
+To re-write the image, user re-uses the gdcm::FileHelper
+
+fh->SetImageData( userPixels, userPixelsLength);
+fh->SetTypeToRaw(); // Even if it was possible to convert Palette to RGB
+                     // (WriteMode is set)
+ 
+fh->SetWriteTypeToDcmExpl(); // he wants Explicit Value Representation
+                              // Little Endian is the default
+                              // no other value is allowed
+                                (-->SetWriteType(ExplicitVR);)
+                                   -->WriteType = ExplicitVR;
+fh->Write(newFileName);      // overwrites the file, if any
+
+// or :
+fh->WriteDcmExplVR(newFileName);
+
+
+// ----------------------------- WARNING -------------------------
+
+These lines will be moved to the document-to-be 'Developer's Guide'
+
+WriteMode : WMODE_RAW / WMODE_RGB
+WriteType : ImplicitVR, ExplicitVR, ACR, ACR_LIBIDO
+
+fh1->Write(newFileName);
+   SetWriteFileTypeToImplicitVR() / SetWriteFileTypeToExplicitVR();
+   (modifies TransferSyntax)
+   SetWriteToRaw(); / SetWriteToRGB();
+      (modifies, when necessary : photochromatic interpretation, 
+         samples per pixel, Planar configuration, 
+         bits allocated, bits stored, high bit -ACR 24 bits-
+         Pixels element VR, pushes out the LUT )
+   CheckWriteIntegrity();
+      (checks user given pixels length)
+   FileInternal->Write(fileName,WriteType)
+   fp = opens file(fileName);
+   ComputeGroup0002Length( );
+   BitsAllocated 12->16
+      RemoveEntryNoDestroy(palettes, etc)
+      Document::WriteContent(fp, writetype);
+   RestoreWrite();
+      (moves back to the File all the archived elements)
+   RestoreWriteFileType();
+      (pushes back group 0002, with TransferSyntax)
+*/
+
+
+
+
+namespace gdcm 
+{
+//-------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3
+ *        file (gdcm::File only deals with the ... header)
+ *        Opens (in read only and when possible) an existing file and checks
+ *        for DICOM compliance. Returns NULL on failure.
+ *        It will be up to the user to load the pixels into memory
+ *        ( GetImageDataSize() + GetImageData() methods)
+ * \note  the in-memory representation of all available tags found in
+ *        the DICOM header is post-poned to first header information access.
+ *        This avoid a double parsing of public part of the header when
+ *        one sets an a posteriori shadow dictionary (efficiency can be
+ *        seen as a side effect).   
+ */
+FileHelper::FileHelper( )
+{ 
+   FileInternal = new File( );
+   SelfHeader = true;
+   Initialize();
+}
+
+/**
+ * \brief Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3
+ *        file (File only deals with the ... header)
+ *        Opens (in read only and when possible) an existing file and checks
+ *        for DICOM compliance. Returns NULL on failure.
+ *        It will be up to the user to load the pixels into memory
+ *        ( GetImageDataSize() + GetImageData() methods)
+ * \note  the in-memory representation of all available tags found in
+ *        the DICOM header is post-poned to first header information access.
+ *        This avoid a double parsing of public part of the header when
+ *        user sets an a posteriori shadow dictionary (efficiency can be
+ *        seen as a side effect).   
+ * @param header already built Header
+ */
+FileHelper::FileHelper(File *header)
+{
+   FileInternal = header;
+   SelfHeader = false;
+   Initialize();
+   if ( FileInternal->IsReadable() )
+   {
+      PixelReadConverter->GrabInformationsFromFile( FileInternal );
+   }
+}
+
+#ifndef GDCM_LEGACY_REMOVE
+/**
+ * \brief DEPRECATED : use SetFilename() + SetLoadMode() + Load() methods
+ *        Constructor dedicated to deal with the *pixels* area of a ACR/DICOMV3
+ *        file (gdcm::File only deals with the ... header)
+ *        Opens (in read only and when possible) an existing file and checks
+ *        for DICOM compliance. Returns NULL on failure.
+ *        It will be up to the user to load the pixels into memory
+ * \note  the in-memory representation of all available tags found in
+ *        the DICOM header is post-poned to first header information access.
+ *        This avoid a double parsing of public part of the header when
+ *        one sets an a posteriori shadow dictionary (efficiency can be
+ *        seen as a side effect).   
+ * @param filename file to be opened for parsing
+ * @deprecated  use SetFilename() + Load() methods
+ */
+FileHelper::FileHelper(std::string const &filename )
+{
+   FileInternal = new File( );
+   FileInternal->SetFileName( filename );
+   FileInternal->Load();
+   SelfHeader = true;
+   Initialize();
+   if ( FileInternal->IsReadable() )
+   {
+      PixelReadConverter->GrabInformationsFromFile( FileInternal );
+   }
+}
+#endif
+
+/**
+ * \brief canonical destructor
+ * \note  If the header (gdcm::File) was created by the FileHelper constructor,
+ *        it is destroyed by the FileHelper
+ */
+FileHelper::~FileHelper()
+{ 
+   if ( PixelReadConverter )
+   {
+      delete PixelReadConverter;
+   }
+   if ( PixelWriteConverter )
+   {
+      delete PixelWriteConverter;
+   }
+   if ( Archive )
+   {
+      delete Archive;
+   }
+
+   if ( SelfHeader )
+   {
+      delete FileInternal;
+   }
+   FileInternal = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+/**
+ * \brief Sets the LoadMode of the internal gdcm::File as a boolean string. 
+ *        NO_SEQ, NO_SHADOW, NO_SHADOWSEQ ... (nothing more, right now)
+ *        WARNING : before using NO_SHADOW, be sure *all* your files
+ *        contain accurate values in the 0x0000 element (if any) 
+ *        of *each* Shadow Group. The parser will fail if the size is wrong !
+ * @param   loadMode Load mode to be used    
+ */
+void FileHelper::SetLoadMode(int loadMode) 
+{ 
+   GetFile()->SetLoadMode( loadMode ); 
+}
+/**
+ * \brief Sets the LoadMode of the internal gdcm::File
+ * @param  fileName name of the file to be open  
+ */
+void FileHelper::SetFileName(std::string const &fileName)
+{
+   FileInternal->SetFileName( fileName );
+}
+
+/**
+ * \brief   Loader  
+ * @return false if file cannot be open or no swap info was found,
+ *         or no tag was found.
+ */
+bool FileHelper::Load()
+{ 
+   if ( !FileInternal->Load() )
+      return false;
+
+   PixelReadConverter->GrabInformationsFromFile( FileInternal );
+   return true;
+}
+
+/**
+ * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
+ *          through it's (group, element) and modifies it's content with
+ *          the given value.
+ * @param   content new value (string) to substitute with
+ * @param   group  group number of the Dicom Element to modify
+ * @param   elem element number of the Dicom Element to modify
+ * \return  false if DocEntry not found
+ */
+bool FileHelper::SetValEntry(std::string const &content,
+                             uint16_t group, uint16_t elem)
+{ 
+   return FileInternal->SetValEntry(content, group, elem);
+}
+
+
+/**
+ * \brief   Accesses an existing DocEntry (i.e. a Dicom Element)
+ *          through it's (group, element) and modifies it's content with
+ *          the given value.
+ * @param   content new value (void*  -> uint8_t*) to substitute with
+ * @param   lgth new value length
+ * @param   group  group number of the Dicom Element to modify
+ * @param   elem element number of the Dicom Element to modify
+ * \return  false if DocEntry not found
+ */
+bool FileHelper::SetBinEntry(uint8_t *content, int lgth,
+                             uint16_t group, uint16_t elem)
+{
+   return FileInternal->SetBinEntry(content, lgth, group, elem);
+}
+
+/**
+ * \brief   Modifies the value of a given DocEntry (Dicom entry)
+ *          when it exists. Creates it with the given value when unexistant.
+ * @param   content (string)value to be set
+ * @param   group   Group number of the Entry 
+ * @param   elem  Element number of the Entry
+ * \return  pointer to the modified/created Dicom entry (NULL when creation
+ *          failed).
+ */ 
+ValEntry *FileHelper::InsertValEntry(std::string const &content,
+                                     uint16_t group, uint16_t elem)
+{
+   return FileInternal->InsertValEntry(content, group, elem);
+}
+
+/**
+ * \brief   Modifies the value of a given DocEntry (Dicom entry)
+ *          when it exists. Creates it with the given value when unexistant.
+ *          A copy of the binArea is made to be kept in the Document.
+ * @param   binArea (binary)value to be set
+ * @param   lgth new value length
+ * @param   group   Group number of the Entry 
+ * @param   elem  Element number of the Entry
+ * \return  pointer to the modified/created Dicom entry (NULL when creation
+ *          failed).
+ */
+BinEntry *FileHelper::InsertBinEntry(uint8_t *binArea, int lgth,
+                                     uint16_t group, uint16_t elem)
+{
+   return FileInternal->InsertBinEntry(binArea, lgth, group, elem);
+}
+
+/**
+ * \brief   Adds an empty SeqEntry 
+ *          (remove any existing entry with same group,elem)
+ * @param   group   Group number of the Entry 
+ * @param   elem  Element number of the Entry
+ * \return  pointer to the created SeqEntry (NULL when creation
+ *          failed).
+ */
+SeqEntry *FileHelper::InsertSeqEntry(uint16_t group, uint16_t elem)
+{
+   return FileInternal->InsertSeqEntry(group, elem);
+}
+
+/**
+ * \brief   Get the size of the image data
+ *          If the image can be RGB (with a lut or by default), the size 
+ *          corresponds to the RGB image
+ *         (use GetImageDataRawSize if you want to be sure to get *only*
+ *          the size of the pixels)
+ * @return  The image size
+ */
+size_t FileHelper::GetImageDataSize()
+{
+   if ( PixelWriteConverter->GetUserData() )
+   {
+      return PixelWriteConverter->GetUserDataSize();
+   }
+   return PixelReadConverter->GetRGBSize();
+}
+
+/**
+ * \brief   Get the size of the image data.
+ *          If the image could be converted to RGB using a LUT, 
+ *          this transformation is not taken into account by GetImageDataRawSize
+ *          (use GetImageDataSize if you wish)
+ * @return  The raw image size
+ */
+size_t FileHelper::GetImageDataRawSize()
+{
+   if ( PixelWriteConverter->GetUserData() )
+   {
+      return PixelWriteConverter->GetUserDataSize();
+   }
+   return PixelReadConverter->GetRawSize();
+}
+
+/**
+ * \brief brings pixels into memory :  
+ *          - Allocates necessary memory,
+ *          - Reads the pixels from disk (uncompress if necessary),
+ *          - Transforms YBR pixels, if any, into RGB pixels,
+ *          - Transforms 3 planes R, G, B, if any, into a single RGB Plane
+ *          - Transforms single Grey plane + 3 Palettes into a RGB Plane
+ *          - Copies the pixel data (image[s]/volume[s]) to newly allocated zone.
+ * @return  Pointer to newly allocated pixel data.
+ *          (uint8_t is just for prototyping. feel free to cast)
+ *          NULL if alloc fails 
+ */
+uint8_t *FileHelper::GetImageData()
+{
+   if ( PixelWriteConverter->GetUserData() )
+   {
+      return PixelWriteConverter->GetUserData();
+   }
+
+   if ( ! GetRaw() )
+   {
+      // If the decompression failed nothing can be done.
+      return 0;
+   }
+
+   if ( FileInternal->HasLUT() && PixelReadConverter->BuildRGBImage() )
+   {
+      return PixelReadConverter->GetRGB();
+   }
+   else
+   {
+      // When no LUT or LUT conversion fails, return the Raw
+      return PixelReadConverter->GetRaw();
+   }
+}
+
+/**
+ * \brief brings pixels into memory :  
+ *          - Allocates necessary memory, 
+ *          - Transforms YBR pixels (if any) into RGB pixels
+ *          - Transforms 3 planes R, G, B  (if any) into a single RGB Plane
+ *          - Copies the pixel data (image[s]/volume[s]) to newly allocated zone. 
+ *          - DOES NOT transform Grey plane + 3 Palettes into a RGB Plane
+ * @return  Pointer to newly allocated pixel data.
+ *          (uint8_t is just for prototyping. feel free to cast)
+ *          NULL if alloc fails
+ */
+uint8_t *FileHelper::GetImageDataRaw ()
+{
+   return GetRaw();
+}
+
+#ifndef GDCM_LEGACY_REMOVE
+/*
+ * \brief   Useless function, since PixelReadConverter forces us 
+ *          copy the Pixels anyway.  
+ *          Reads the pixels from disk (uncompress if necessary),
+ *          Transforms YBR pixels, if any, into RGB pixels
+ *          Transforms 3 planes R, G, B, if any, into a single RGB Plane
+ *          Transforms single Grey plane + 3 Palettes into a RGB Plane   
+ *          Copies at most MaxSize bytes of pixel data to caller allocated
+ *          memory space.
+ * \warning This function allows people that want to build a volume
+ *          from an image stack *not to* have, first to get the image pixels, 
+ *          and then move them to the volume area.
+ *          It's absolutely useless for any VTK user since vtk chooses 
+ *          to invert the lines of an image, that is the last line comes first
+ *          (for some axis related reasons?). Hence he will have 
+ *          to load the image line by line, starting from the end.
+ *          VTK users have to call GetImageData
+ *     
+ * @param   destination Address (in caller's memory space) at which the
+ *          pixel data should be copied
+ * @param   maxSize Maximum number of bytes to be copied. When MaxSize
+ *          is not sufficient to hold the pixel data the copy is not
+ *          executed (i.e. no partial copy).
+ * @return  On success, the number of bytes actually copied. Zero on
+ *          failure e.g. MaxSize is lower than necessary.
+ */
+size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize)
+{
+   if ( ! GetRaw() )
+   {
+      // If the decompression failed nothing can be done.
+      return 0;
+   }
+
+   if ( FileInternal->HasLUT() && PixelReadConverter->BuildRGBImage() )
+   {
+      if ( PixelReadConverter->GetRGBSize() > maxSize )
+      {
+         gdcmWarningMacro( "Pixel data bigger than caller's expected MaxSize");
+         return 0;
+      }
+      memcpy( destination,
+              (void*)PixelReadConverter->GetRGB(),
+              PixelReadConverter->GetRGBSize() );
+      return PixelReadConverter->GetRGBSize();
+   }
+
+   // Either no LUT conversion necessary or LUT conversion failed
+   if ( PixelReadConverter->GetRawSize() > maxSize )
+   {
+      gdcmWarningMacro( "Pixel data bigger than caller's expected MaxSize");
+      return 0;
+   }
+   memcpy( destination,
+           (void *)PixelReadConverter->GetRaw(),
+           PixelReadConverter->GetRawSize() );
+   return PixelReadConverter->GetRawSize();
+}
+#endif
+
+/**
+ * \brief   Points the internal pointer to the callers inData
+ *          image representation, BUT WITHOUT COPYING THE DATA.
+ *          'image' Pixels are presented as C-like 2D arrays : line per line.
+ *          'volume'Pixels are presented as C-like 3D arrays : plane per plane 
+ * \warning Since the pixels are not copied, it is the caller's responsability
+ *          not to deallocate its data before gdcm uses them (e.g. with
+ *          the Write() method )
+ * @param inData user supplied pixel area (uint8_t* is just for the compiler.
+ *               user is allowed to pass any kind of pixelsn since the size is
+ *               given in bytes) 
+ * @param expectedSize total image size, *in Bytes*
+ */
+void FileHelper::SetImageData(uint8_t *inData, size_t expectedSize)
+{
+   SetUserData(inData, expectedSize);
+}
+
+/**
+ * \brief   Set the image data defined by the user
+ * \warning When writting the file, this data are get as default data to write
+ * @param inData user supplied pixel area (uint8_t* is just for the compiler.
+ *               user is allowed to pass any kind of pixels since the size is
+ *               given in bytes) 
+ * @param expectedSize total image size, *in Bytes* 
+ */
+void FileHelper::SetUserData(uint8_t *inData, size_t expectedSize)
+{
+   PixelWriteConverter->SetUserData(inData, expectedSize);
+}
+
+/**
+ * \brief   Get the image data defined by the user
+ * \warning When writting the file, this data are get as default data to write
+ */
+uint8_t *FileHelper::GetUserData()
+{
+   return PixelWriteConverter->GetUserData();
+}
+
+/**
+ * \brief   Get the image data size defined by the user
+ * \warning When writting the file, this data are get as default data to write
+ */
+size_t FileHelper::GetUserDataSize()
+{
+   return PixelWriteConverter->GetUserDataSize();
+}
+
+/**
+ * \brief   Get the image data from the file.
+ *          If a LUT is found, the data are expanded to be RGB
+ */
+uint8_t *FileHelper::GetRGBData()
+{
+   return PixelReadConverter->GetRGB();
+}
+
+/**
+ * \brief   Get the image data size from the file.
+ *          If a LUT is found, the data are expanded to be RGB
+ */
+size_t FileHelper::GetRGBDataSize()
+{
+   return PixelReadConverter->GetRGBSize();
+}
+
+/**
+ * \brief   Get the image data from the file.
+ *          Even when a LUT is found, the data are not expanded to RGB!
+ */
+uint8_t *FileHelper::GetRawData()
+{
+   return PixelReadConverter->GetRaw();
+}
+
+/**
+ * \brief   Get the image data size from the file.
+ *          Even when a LUT is found, the data are not expanded to RGB!
+ */
+size_t FileHelper::GetRawDataSize()
+{
+   return PixelReadConverter->GetRawSize();
+}
+
+/**
+ * \brief Access to the underlying \ref PixelReadConverter RGBA LUT
+ */
+uint8_t* FileHelper::GetLutRGBA()
+{
+   if ( PixelReadConverter->GetLutRGBA() ==0 )
+      PixelReadConverter->BuildLUTRGBA();
+   return PixelReadConverter->GetLutRGBA();
+}
+
+/**
+ * \brief Access to the underlying \ref PixelReadConverter RGBA LUT Item Number
+ */
+int FileHelper::GetLutItemNumber()
+{
+   return PixelReadConverter->GetLutItemNumber();
+}
+
+/**
+ * \brief Access to the underlying \ref PixelReadConverter RGBA LUT Item Size
+ */
+int FileHelper::GetLutItemSize()
+{
+   return PixelReadConverter->GetLutItemSize();
+}
+
+/**
+ * \brief Writes on disk A SINGLE Dicom file
+ *        NO test is performed on  processor "Endiannity".
+ *        It's up to the user to call his Reader properly
+ * @param fileName name of the file to be created
+ *                 (any already existing file is over written)
+ * @return false if write fails
+ */
+bool FileHelper::WriteRawData(std::string const &fileName)
+{
+   std::ofstream fp1(fileName.c_str(), std::ios::out | std::ios::binary );
+   if (!fp1)
+   {
+      gdcmWarningMacro( "Fail to open (write) file:" << fileName.c_str());
+      return false;
+   }
+
+   if ( PixelWriteConverter->GetUserData() )
+   {
+      fp1.write( (char *)PixelWriteConverter->GetUserData(), 
+                 PixelWriteConverter->GetUserDataSize() );
+   }
+   else if ( PixelReadConverter->GetRGB() )
+   {
+      fp1.write( (char *)PixelReadConverter->GetRGB(), 
+                 PixelReadConverter->GetRGBSize());
+   }
+   else if ( PixelReadConverter->GetRaw() )
+   {
+      fp1.write( (char *)PixelReadConverter->GetRaw(), 
+                 PixelReadConverter->GetRawSize());
+   }
+   else
+   {
+      gdcmErrorMacro( "Nothing written." );
+   }
+
+   fp1.close();
+
+   return true;
+}
+
+/**
+ * \brief Writes on disk A SINGLE Dicom file, 
+ *        using the Implicit Value Representation convention
+ *        NO test is performed on  processor "Endianity".
+ * @param fileName name of the file to be created
+ *                 (any already existing file is overwritten)
+ * @return false if write fails
+ */
+
+bool FileHelper::WriteDcmImplVR (std::string const &fileName)
+{
+   SetWriteTypeToDcmImplVR();
+   return Write(fileName);
+}
+
+/**
+* \brief Writes on disk A SINGLE Dicom file, 
+ *        using the Explicit Value Representation convention
+ *        NO test is performed on  processor "Endiannity". 
+ * @param fileName name of the file to be created
+ *                 (any already existing file is overwritten)
+ * @return false if write fails
+ */
+
+bool FileHelper::WriteDcmExplVR (std::string const &fileName)
+{
+   SetWriteTypeToDcmExplVR();
+   return Write(fileName);
+}
+
+/**
+ * \brief Writes on disk A SINGLE Dicom file, 
+ *        using the ACR-NEMA convention
+ *        NO test is performed on  processor "Endiannity".
+ *        (a l'attention des logiciels cliniques 
+ *        qui ne prennent en entr�e QUE des images ACR ...
+ * \warning if a DICOM_V3 header is supplied,
+ *         groups < 0x0008 and shadow groups are ignored
+ * \warning NO TEST is performed on processor "Endiannity".
+ * @param fileName name of the file to be created
+ *                 (any already existing file is overwritten)
+ * @return false if write fails
+ */
+
+bool FileHelper::WriteAcr (std::string const &fileName)
+{
+   SetWriteTypeToAcr();
+   return Write(fileName);
+}
+
+/**
+ * \brief Writes on disk A SINGLE Dicom file, 
+ * @param fileName name of the file to be created
+ *                 (any already existing file is overwritten)
+ * @return false if write fails
+ */
+bool FileHelper::Write(std::string const &fileName)
+{
+   switch(WriteType)
+   {
+      case ImplicitVR:
+         SetWriteFileTypeToImplicitVR();
+         break;
+      case Unknown:  // should never happen; ExplicitVR is the default value
+      case ExplicitVR:
+         SetWriteFileTypeToExplicitVR();
+         break;
+      case ACR:
+      case ACR_LIBIDO:
+      // NOTHING is done here just for LibIDO.
+      // Just to avoid further trouble if user creates a file ex-nihilo,
+      // wants to write it as an ACR-NEMA file,
+      // and forgets to create any Entry belonging to group 0008
+      // (shame on him !)
+      // We add Recognition Code (RET)
+        if ( ! FileInternal->GetValEntry(0x0008, 0x0010) )
+            FileInternal->InsertValEntry("", 0x0008, 0x0010);
+         SetWriteFileTypeToACR();
+        // SetWriteFileTypeToImplicitVR(); // ACR IS implicit VR !
+         break;
+      case JPEG:
+         SetWriteFileTypeToJPEG();
+         break;
+   }
+   CheckMandatoryElements();
+
+   // --------------------------------------------------------------
+   // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
+   //
+   // if recognition code tells us we dealt with a LibIDO image
+   // we reproduce on disk the switch between lineNumber and columnNumber
+   // just before writting ...
+   /// \todo the best trick would be *change* the recognition code
+   ///       but pb expected if user deals with, e.g. COMPLEX images
+   
+   if ( WriteType == ACR_LIBIDO )
+   {
+      SetWriteToLibido();
+   }
+   else
+   {
+      SetWriteToNoLibido();
+   }
+   // ----------------- End of Special Patch ----------------
+  
+   switch(WriteMode)
+   {
+      case WMODE_RAW :
+         SetWriteToRaw(); // modifies and pushes to the archive, when necessary
+         break;
+      case WMODE_RGB :
+         SetWriteToRGB(); // modifies and pushes to the archive, when necessary
+         break;
+   }
+
+   bool check = CheckWriteIntegrity(); // verifies length
+   if (WriteType == JPEG ) check = true;
+   if (check)
+   {
+      check = FileInternal->Write(fileName,WriteType);
+   }
+
+   RestoreWrite();
+   RestoreWriteFileType();
+   RestoreWriteMandatory();
+
+   // --------------------------------------------------------------
+   // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
+   // 
+   // ...and we restore the header to be Dicom Compliant again 
+   // just after writting
+   RestoreWriteOfLibido();
+   // ----------------- End of Special Patch ----------------
+
+   return check;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+/**
+ * \brief Checks the write integrity
+ *
+ * The tests made are :
+ *  - verify the size of the image to write with the possible write
+ *    when the user set an image data
+ * @return true if check is successfull
+ */
+bool FileHelper::CheckWriteIntegrity()
+{
+   if ( PixelWriteConverter->GetUserData() )
+   {
+      int numberBitsAllocated = FileInternal->GetBitsAllocated();
+      if ( numberBitsAllocated == 0 || numberBitsAllocated == 12 )
+      {
+         gdcmWarningMacro( "numberBitsAllocated changed from " 
+                          << numberBitsAllocated << " to 16 " 
+                          << " for consistency purpose" );
+         numberBitsAllocated = 16;
+      }
+
+      size_t decSize = FileInternal->GetXSize()
+                     * FileInternal->GetYSize() 
+                     * FileInternal->GetZSize()
+                     * FileInternal->GetSamplesPerPixel()
+                     * ( numberBitsAllocated / 8 );
+      size_t rgbSize = decSize;
+      if ( FileInternal->HasLUT() )
+         rgbSize = decSize * 3;
+
+      switch(WriteMode)
+      {
+         case WMODE_RAW :
+            if ( decSize!=PixelWriteConverter->GetUserDataSize() )
+            {
+               gdcmWarningMacro( "Data size (Raw) is incorrect. Should be " 
+                           << decSize << " / Found :" 
+                           << PixelWriteConverter->GetUserDataSize() );
+               return false;
+            }
+            break;
+         case WMODE_RGB :
+            if ( rgbSize!=PixelWriteConverter->GetUserDataSize() )
+            {
+               gdcmWarningMacro( "Data size (RGB) is incorrect. Should be " 
+                          << decSize << " / Found " 
+                          << PixelWriteConverter->GetUserDataSize() );
+               return false;
+            }
+            break;
+      }
+   }
+
+   return true;
+}
+
+/**
+ * \brief Updates the File to write RAW data (as opposed to RGB data)
+ *       (modifies, when necessary, photochromatic interpretation, 
+ *       bits allocated, Pixels element VR)
+ */ 
+void FileHelper::SetWriteToRaw()
+{
+   if ( FileInternal->GetNumberOfScalarComponents() == 3 
+    && !FileInternal->HasLUT() )
+   {
+      SetWriteToRGB();
+   } 
+   else
+   {
+      ValEntry *photInt = CopyValEntry(0x0028,0x0004);
+      if (FileInternal->HasLUT() )
+      {
+         photInt->SetValue("PALETTE COLOR ");
+      }
+      else
+      {
+         photInt->SetValue("MONOCHROME2 ");
+      }
+
+      PixelWriteConverter->SetReadData(PixelReadConverter->GetRaw(),
+                                       PixelReadConverter->GetRawSize());
+
+      std::string vr = "OB";
+      if ( FileInternal->GetBitsAllocated()>8 )
+         vr = "OW";
+      if ( FileInternal->GetBitsAllocated()==24 ) // For RGB ACR files 
+         vr = "OB";
+      BinEntry *pixel = 
+         CopyBinEntry(GetFile()->GetGrPixel(),GetFile()->GetNumPixel(),vr);
+      pixel->SetValue(GDCM_BINLOADED);
+      pixel->SetBinArea(PixelWriteConverter->GetData(),false);
+      pixel->SetLength(PixelWriteConverter->GetDataSize());
+
+      Archive->Push(photInt);
+      Archive->Push(pixel);
+   }
+}
+
+/**
+ * \brief Updates the File to write RGB data (as opposed to RAW data)
+ *       (modifies, when necessary, photochromatic interpretation, 
+ *       samples per pixel, Planar configuration, 
+ *       bits allocated, bits stored, high bit -ACR 24 bits-
+ *       Pixels element VR, pushes out the LUT, )
+ */ 
+void FileHelper::SetWriteToRGB()
+{
+   if ( FileInternal->GetNumberOfScalarComponents()==3 )
+   {
+      PixelReadConverter->BuildRGBImage();
+      
+      ValEntry *spp = CopyValEntry(0x0028,0x0002);
+      spp->SetValue("3 ");
+
+      ValEntry *planConfig = CopyValEntry(0x0028,0x0006);
+      planConfig->SetValue("0 ");
+
+      ValEntry *photInt = CopyValEntry(0x0028,0x0004);
+      photInt->SetValue("RGB ");
+
+      if ( PixelReadConverter->GetRGB() )
+      {
+         PixelWriteConverter->SetReadData(PixelReadConverter->GetRGB(),
+                                          PixelReadConverter->GetRGBSize());
+      }
+      else // Raw data
+      {
+         PixelWriteConverter->SetReadData(PixelReadConverter->GetRaw(),
+                                          PixelReadConverter->GetRawSize());
+      }
+
+      std::string vr = "OB";
+      if ( FileInternal->GetBitsAllocated()>8 )
+         vr = "OW";
+      if ( FileInternal->GetBitsAllocated()==24 ) // For RGB ACR files 
+         vr = "OB";
+      BinEntry *pixel = 
+         CopyBinEntry(GetFile()->GetGrPixel(),GetFile()->GetNumPixel(),vr);
+      pixel->SetValue(GDCM_BINLOADED);
+      pixel->SetBinArea(PixelWriteConverter->GetData(),false);
+      pixel->SetLength(PixelWriteConverter->GetDataSize());
+
+      Archive->Push(spp);
+      Archive->Push(planConfig);
+      Archive->Push(photInt);
+      Archive->Push(pixel);
+
+      // Remove any LUT
+      Archive->Push(0x0028,0x1101);
+      Archive->Push(0x0028,0x1102);
+      Archive->Push(0x0028,0x1103);
+      Archive->Push(0x0028,0x1201);
+      Archive->Push(0x0028,0x1202);
+      Archive->Push(0x0028,0x1203);
+
+      // push out Palette Color Lookup Table UID, if any
+      Archive->Push(0x0028,0x1199);
+
+      // For old '24 Bits' ACR-NEMA
+      // Thus, we have a RGB image and the bits allocated = 24 and 
+      // samples per pixels = 1 (in the read file)
+      if ( FileInternal->GetBitsAllocated()==24 ) 
+      {
+         ValEntry *bitsAlloc = CopyValEntry(0x0028,0x0100);
+         bitsAlloc->SetValue("8 ");
+
+         ValEntry *bitsStored = CopyValEntry(0x0028,0x0101);
+         bitsStored->SetValue("8 ");
+
+         ValEntry *highBit = CopyValEntry(0x0028,0x0102);
+         highBit->SetValue("7 ");
+
+         Archive->Push(bitsAlloc);
+         Archive->Push(bitsStored);
+         Archive->Push(highBit);
+      }
+   }
+   else
+   {
+      SetWriteToRaw();
+   }
+}
+
+/**
+ * \brief Restore the File write mode  
+ */ 
+void FileHelper::RestoreWrite()
+{
+   Archive->Restore(0x0028,0x0002);
+   Archive->Restore(0x0028,0x0004);
+   Archive->Restore(0x0028,0x0006);
+   Archive->Restore(GetFile()->GetGrPixel(),GetFile()->GetNumPixel());
+
+   // For old ACR-NEMA (24 bits problem)
+   Archive->Restore(0x0028,0x0100);
+   Archive->Restore(0x0028,0x0101);
+   Archive->Restore(0x0028,0x0102);
+
+   // For the LUT
+   Archive->Restore(0x0028,0x1101);
+   Archive->Restore(0x0028,0x1102);
+   Archive->Restore(0x0028,0x1103);
+   Archive->Restore(0x0028,0x1201);
+   Archive->Restore(0x0028,0x1202);
+   Archive->Restore(0x0028,0x1203);
+
+   // For the Palette Color Lookup Table UID
+   Archive->Restore(0x0028,0x1203); 
+
+
+   // group 0002 may be pushed out for ACR-NEMA writting purposes 
+   Archive->Restore(0x0002,0x0000);
+   Archive->Restore(0x0002,0x0001);
+   Archive->Restore(0x0002,0x0002);
+   Archive->Restore(0x0002,0x0003);
+   Archive->Restore(0x0002,0x0010);
+   Archive->Restore(0x0002,0x0012);
+   Archive->Restore(0x0002,0x0013);
+   Archive->Restore(0x0002,0x0016);
+   Archive->Restore(0x0002,0x0100);
+   Archive->Restore(0x0002,0x0102);
+}
+
+/**
+ * \brief Pushes out the whole group 0002
+ *        FIXME : better, set a flag to tell the writer not to write it ...
+ *        FIXME : method should probably have an other name !
+ *                SetWriteFileTypeToACR is NOT opposed to 
+ *                SetWriteFileTypeToExplicitVR and SetWriteFileTypeToImplicitVR
+ */ 
+void FileHelper::SetWriteFileTypeToACR()
+{
+   Archive->Push(0x0002,0x0000);
+   Archive->Push(0x0002,0x0001);
+   Archive->Push(0x0002,0x0002);
+   Archive->Push(0x0002,0x0003);
+   Archive->Push(0x0002,0x0010);
+   Archive->Push(0x0002,0x0012);
+   Archive->Push(0x0002,0x0013);
+   Archive->Push(0x0002,0x0016);
+   Archive->Push(0x0002,0x0100);
+   Archive->Push(0x0002,0x0102);
+}
+
+/**
+ * \brief Sets in the File the TransferSyntax to 'JPEG'
+ */ 
+void FileHelper::SetWriteFileTypeToJPEG()
+{
+   std::string ts = Util::DicomString( 
+      Global::GetTS()->GetSpecialTransferSyntax(TS::JPEGBaselineProcess1) );
+
+   ValEntry *tss = CopyValEntry(0x0002,0x0010);
+   tss->SetValue(ts);
+
+   Archive->Push(tss);
+}
+
+/**
+ * \brief Sets in the File the TransferSyntax to 'Explicit VR Little Endian"   
+ */ 
+void FileHelper::SetWriteFileTypeToExplicitVR()
+{
+   std::string ts = Util::DicomString( 
+      Global::GetTS()->GetSpecialTransferSyntax(TS::ExplicitVRLittleEndian) );
+
+   ValEntry *tss = CopyValEntry(0x0002,0x0010);
+   tss->SetValue(ts);
+
+   Archive->Push(tss);
+}
+
+/**
+ * \brief Sets in the File the TransferSyntax to 'Implicit VR Little Endian"   
+ */ 
+void FileHelper::SetWriteFileTypeToImplicitVR()
+{
+   std::string ts = Util::DicomString(
+      Global::GetTS()->GetSpecialTransferSyntax(TS::ImplicitVRLittleEndian) );
+
+   ValEntry *tss = CopyValEntry(0x0002,0x0010);
+   tss->SetValue(ts);
+
+   Archive->Push(tss);
+}
+
+
+/**
+ * \brief Restore in the File the initial group 0002
+ */ 
+void FileHelper::RestoreWriteFileType()
+{
+}
+
+/**
+ * \brief Set the Write not to Libido format
+ */ 
+void FileHelper::SetWriteToLibido()
+{
+   ValEntry *oldRow = dynamic_cast<ValEntry *>
+                (FileInternal->GetDocEntry(0x0028, 0x0010));
+   ValEntry *oldCol = dynamic_cast<ValEntry *>
+                (FileInternal->GetDocEntry(0x0028, 0x0011));
+   
+   if ( oldRow && oldCol )
+   {
+      std::string rows, columns; 
+
+      ValEntry *newRow=new ValEntry(oldRow->GetDictEntry());
+      ValEntry *newCol=new ValEntry(oldCol->GetDictEntry());
+
+      newRow->Copy(oldCol);
+      newCol->Copy(oldRow);
+
+      newRow->SetValue(oldCol->GetValue());
+      newCol->SetValue(oldRow->GetValue());
+
+      Archive->Push(newRow);
+      Archive->Push(newCol);
+   }
+
+   ValEntry *libidoCode = CopyValEntry(0x0008,0x0010);
+   libidoCode->SetValue("ACRNEMA_LIBIDO_1.1");
+   Archive->Push(libidoCode);
+}
+
+/**
+ * \brief Set the Write not to No Libido format
+ */ 
+void FileHelper::SetWriteToNoLibido()
+{
+   ValEntry *recCode = dynamic_cast<ValEntry *>
+                (FileInternal->GetDocEntry(0x0008,0x0010));
+   if ( recCode )
+   {
+      if ( recCode->GetValue() == "ACRNEMA_LIBIDO_1.1" )
+      {
+         ValEntry *libidoCode = CopyValEntry(0x0008,0x0010);
+         libidoCode->SetValue("");
+         Archive->Push(libidoCode);
+      }
+   }
+}
+
+/**
+ * \brief Restore the Write format
+ */ 
+void FileHelper::RestoreWriteOfLibido()
+{
+   Archive->Restore(0x0028,0x0010);
+   Archive->Restore(0x0028,0x0011);
+   Archive->Restore(0x0008,0x0010);
+
+   // Restore 'LibIDO-special' entries, if any
+   Archive->Restore(0x0028,0x0015);
+   Archive->Restore(0x0028,0x0016);
+   Archive->Restore(0x0028,0x0017);
+   Archive->Restore(0x0028,0x00199);
+}
+
+/**
+ * \brief Duplicates a ValEntry or creates it.
+ * @param   group   Group number of the Entry 
+ * @param   elem  Element number of the Entry
+ * \return  pointer to the new Val Entry (NULL when creation failed).          
+ */ 
+ValEntry *FileHelper::CopyValEntry(uint16_t group, uint16_t elem)
+{
+   DocEntry *oldE = FileInternal->GetDocEntry(group, elem);
+   ValEntry *newE;
+
+   if ( oldE )
+   {
+      newE = new ValEntry(oldE->GetDictEntry());
+      newE->Copy(oldE);
+   }
+   else
+   {
+      newE = GetFile()->NewValEntry(group, elem);
+   }
+
+   return newE;
+}
+
+/**
+ * \brief   Duplicates a BinEntry or creates it.
+ * @param   group   Group number of the Entry 
+ * @param   elem  Element number of the Entry
+ * @param   vr  Value Representation of the Entry
+ *          FIXME : what is it used for?
+ * \return  pointer to the new Bin Entry (NULL when creation failed).
+ */ 
+BinEntry *FileHelper::CopyBinEntry(uint16_t group, uint16_t elem,
+                                   const TagName &vr)
+{
+   DocEntry *oldE = FileInternal->GetDocEntry(group, elem);
+   BinEntry *newE;
+
+   if ( oldE && vr != GDCM_UNKNOWN ) 
+      if ( oldE->GetVR() != vr )
+         oldE = NULL;
+
+   if ( oldE )
+   {
+      newE = new BinEntry(oldE->GetDictEntry());
+      newE->Copy(oldE);
+   }
+   else
+   {
+      newE = GetFile()->NewBinEntry(group, elem, vr);
+   }
+
+   return newE;
+}
+
+/**
+ * \brief   This method is called automatically, just before writting
+ *         in order to produce a 'True Dicom V3' image.
+ *
+ *         We cannot know *how* the user made the File :
+ *         (reading an old ACR-NEMA file or a not very clean DICOM file ...) 
+ *          Just before writting :
+ *             - we check the Entries
+ *             - we create the mandatory entries if they are missing
+ *             - we modify the values if necessary
+ *             - we push the sensitive entries to the Archive
+ *          The writing process will restore the entries as they where before 
+ *          entering FileHelper::CheckMandatoryElements, so the user will always
+ *          see the entries just as they were before he decided to write.
+ *
+ * \note
+ *       -  Entries whose type is 1 are mandatory, with a mandatory value
+ *       -  Entries whose type is 1c are mandatory-inside-a-Sequence,
+ *                             with a mandatory value
+ *       -  Entries whose type is 2 are mandatory, with an optional value
+ *       -  Entries whose type is 2c are mandatory-inside-a-Sequence,
+ *                             with an optional value
+ *       -  Entries whose type is 3 are optional
+ * 
+ * \todo 
+ *         - warn the user if we had to add some entries :
+ *         even if a mandatory entry is missing, we add it, with a default value
+ *         (we don't want to give up the writting process if user forgot to
+ *         specify Lena's Patient ID, for instance ...)
+ *         - read the whole PS 3.3 Part of DICOM  (890 pages)
+ *         and write a *full* checker (probably one method per Modality ...)
+ *         Any contribution is welcome. 
+ *         - write a user callable full checker, to allow post reading
+ *         and/or pre writting image consistency check.           
+ */ 
+
+/* -------------------------------------------------------------------------------------
+To be moved to User's guide / WIKI  ?
+
+We have to deal with 4 *very* different cases :
+-1) user created ex nihilo his own image  and wants to write it as a Dicom image.
+-2) user modified the pixels of an existing image.
+-3) user created a new image, using existing images (eg MIP, MPR, cartography image)
+-4) user anonymized an image without processing the pixels.
+
+gdcm::FileHelper::CheckMandatoryElements() deals automatically with these cases.
+
+1)2)3)4)
+0008 0012 Instance Creation Date
+0008 0013 Instance Creation Time
+0008 0018 SOP Instance UID
+are *always* created with the current values; user has *no* possible intervention on
+them.
+
+'Serie Instance UID'(0x0020,0x000e)
+'Study Instance UID'(0x0020,0x000d) are kept as is if already exist,
+                                    created  if it doesn't.
+ The user is allowed to create his own Series/Studies, 
+     keeping the same 'Serie Instance UID' / 'Study Instance UID' for various images
+ Warning :     
+ The user shouldn't add any image to a 'Manufacturer Serie'
+     but there is no way no to allowed him to do that
+     
+ None of the 'shadow elements' are droped out.
+     
+
+1)
+'Modality' (0x0008,0x0060)       is defaulted to "OT" (other) if missing.
+'Conversion Type (0x0008,0x0064) is forced to 'SYN' (Synthetic Image).
+'Study Date', 'Study Time' are defaulted to current Date and Time.
+ 
+1)2)3)
+'Media Storage SOP Class UID' (0x0002,0x0002)
+'SOP Class UID'               (0x0008,0x0016) are set to 
+                                               [Secondary Capture Image Storage]
+'Image Type'                  (0x0008,0x0008) is forced to  "DERIVED\PRIMARY"
+Conversion Type               (0x0008,0x0064) is forced to 'SYN' (Synthetic Image)
+
+2)4)
+If 'SOP Class UID' exists in the native image  ('true DICOM' image)
+    we create the 'Source Image Sequence' SeqEntry (0x0008, 0x2112)    
+    --> 'Referenced SOP Class UID' (0x0008, 0x1150)
+         whose value is the original 'SOP Class UID'
+    --> 'Referenced SOP Instance UID' (0x0008, 0x1155)
+         whose value is the original 'SOP Class UID'
+
+3) TODO : find a trick to allow user to pass to the writter the list of the Dicom images 
+          or the Series, (or the Study ?) he used to created his image 
+          (MIP, MPR, cartography image, ...)
+           These info should be stored (?)
+          0008 1110 SQ 1 Referenced Study Sequence
+          0008 1115 SQ 1 Referenced Series Sequence
+          0008 1140 SQ 1 Referenced Image Sequence
+       
+4) When user *knows* he didn't modified the pixels, he may ask the writer to keep some
+informations unchanged :
+'Media Storage SOP Class UID' (0x0002,0x0002)
+'SOP Class UID'               (0x0008,0x0016)
+'Image Type'                  (0x0008,0x0008)
+'Conversion Type'             (0x0008,0x0064)
+He has to use gdcm::FileHelper::SetKeepMediaStorageSOPClassUID(true)
+(probabely name has to be changed)
+
+
+Bellow follows the full description (hope so !) of the consistency checks performed 
+by gdcm::FileHelper::CheckMandatoryElements()
+
+
+-->'Media Storage SOP Class UID' (0x0002,0x0002)
+-->'SOP Class UID'               (0x0008,0x0016) are set to 
+                                               [Secondary Capture Image Storage]
+   (Potentialy, the image was modified by user, and post-processed; 
+    it's no longer a 'native' image)
+  Except if user told he wants to keep MediaStorageSOPClassUID,
+  when *he* knows he didn't modify the image (e.g. : he just anonymized the file)
+
+--> 'Image Type'  (0x0008,0x0008)
+     is forced to  "DERIVED\PRIMARY"
+     (The written image is no longer an 'ORIGINAL' one)
+  Except if user told he wants to keep MediaStorageSOPClassUID,
+  when *he* knows he didn't modify the image (e.g. : he just anonymized the file)
+   
+ -->  Conversion Type (0x0008,0x0064)
+     is forced to 'SYN' (Synthetic Image)
+  Except if user told he wants to keep MediaStorageSOPClassUID,
+  when *he* knows he didn't modify the image (e.g. : he just anonymized the file)
+            
+--> 'Modality' (0x0008,0x0060)   
+    is defaulted to "OT" (other) if missing.   
+    (a fully user created image belongs to *no* modality)
+      
+--> 'Media Storage SOP Instance UID' (0x0002,0x0003)
+--> 'Implementation Class UID'       (0x0002,0x0012)
+    are automatically generated; no user intervention possible
+
+--> 'Serie Instance UID'(0x0020,0x000e)
+--> 'Study Instance UID'(0x0020,0x000d) are kept as is if already exist
+                                             created  if it doesn't.
+     The user is allowed to create his own Series/Studies, 
+     keeping the same 'Serie Instance UID' / 'Study Instance UID' 
+     for various images
+     Warning :     
+     The user shouldn't add any image to a 'Manufacturer Serie'
+     but there is no way no to allowed him to do that 
+             
+--> If 'SOP Class UID' exists in the native image  ('true DICOM' image)
+    we create the 'Source Image Sequence' SeqEntry (0x0008, 0x2112)
+    
+    --> 'Referenced SOP Class UID' (0x0008, 0x1150)
+         whose value is the original 'SOP Class UID'
+    --> 'Referenced SOP Instance UID' (0x0008, 0x1155)
+         whose value is the original 'SOP Class UID'
+    
+--> Bits Stored, Bits Allocated, Hight Bit Position are checked for consistency
+--> Pixel Spacing     (0x0028,0x0030) is defaulted to "1.0\1.0"
+--> Samples Per Pixel (0x0028,0x0002) is defaulted to 1 (grayscale)
+
+--> Imager Pixel Spacing (0x0018,0x1164) : defaulted to Pixel Spacing value
+
+--> Instance Creation Date, Instance Creation Time are forced to current Date and Time
+
+--> Study Date, Study Time are defaulted to current Date and Time
+   (they remain unchanged if they exist)
+
+--> Patient Orientation : (0x0020,0x0020), if not present, is deduced from 
+    Image Orientation (Patient) : (0020|0037) or from
+    Image Orientation (RET)     : (0020 0035)
+   
+--> Study ID, Series Number, Instance Number, Patient Orientation (Type 2)
+    are created, with empty value if there are missing.
+
+--> Manufacturer, Institution Name, Patient's Name, (Type 2)
+    are defaulted with a 'gdcm' value.
+    
+--> Patient ID, Patient's Birth Date, Patient's Sex, (Type 2)
+--> Referring Physician's Name  (Type 2)
+    are created, with empty value if there are missing.  
+
+ -------------------------------------------------------------------------------------*/
+
+void FileHelper::CheckMandatoryElements()
+{
+   std::string sop =  Util::CreateUniqueUID();
+
+   // just to remember : 'official' 0002 group
+   if ( WriteType != ACR && WriteType != ACR_LIBIDO )
+   {
+     // Group 000002 (Meta Elements) already pushed out
+  
+   //0002 0000 UL 1 Meta Group Length
+   //0002 0001 OB 1 File Meta Information Version
+   //0002 0002 UI 1 Media Stored SOP Class UID
+   //0002 0003 UI 1 Media Stored SOP Instance UID
+   //0002 0010 UI 1 Transfer Syntax UID
+   //0002 0012 UI 1 Implementation Class UID
+   //0002 0013 SH 1 Implementation Version Name
+   //0002 0016 AE 1 Source Application Entity Title
+   //0002 0100 UI 1 Private Information Creator
+   //0002 0102 OB 1 Private Information
+  
+   // Create them if not found
+   // Always modify the value
+   // Push the entries to the archive.
+      CopyMandatoryEntry(0x0002,0x0000,"0");
+
+      BinEntry *e_0002_0001 = CopyBinEntry(0x0002,0x0001, "OB");
+      e_0002_0001->SetBinArea((uint8_t*)Util::GetFileMetaInformationVersion(),
+                               false);
+      e_0002_0001->SetLength(2);
+      Archive->Push(e_0002_0001);
+
+   // 'Media Storage SOP Class UID'  --> [Secondary Capture Image Storage]
+   // Only if not specified by user, to let people create DERIVED images
+   ValEntry *e_0002_0002 = FileInternal->GetValEntry(0x0002, 0x0002);
+   if( !e_0002_0002)
+     {
+     CopyMandatoryEntry(0x0002,0x0002,"1.2.840.10008.5.1.4.1.1.7");    
+     }
+
+   // 'Media Storage SOP Instance UID'   
+   //   CopyMandatoryEntry(0x0002,0x0003,sop);
+      
+   // 'Implementation Class UID'
+      CopyMandatoryEntry(0x0002,0x0012,Util::CreateUniqueUID());
+
+   // 'Implementation Version Name'
+      std::string version = "GDCM ";
+      version += Util::GetVersion();
+      CopyMandatoryEntry(0x0002,0x0013,version);
+   }
+
+   // Push out 'LibIDO-special' entries, if any
+   Archive->Push(0x0028,0x0015);
+   Archive->Push(0x0028,0x0016);
+   Archive->Push(0x0028,0x0017);
+   Archive->Push(0x0028,0x00199);
+
+   // Deal with the pb of (Bits Stored = 12)
+   // - we're gonna write the image as Bits Stored = 16
+   if ( FileInternal->GetEntryValue(0x0028,0x0100) ==  "12")
+   {
+      CopyMandatoryEntry(0x0028,0x0100,"16");
+   }
+
+   // Check if user wasn't drunk ;-)
+
+   itksys_ios::ostringstream s;
+   // check 'Bits Allocated' vs decent values
+   int nbBitsAllocated = FileInternal->GetBitsAllocated();
+   if ( nbBitsAllocated == 0 || nbBitsAllocated > 32)
+   {
+      CopyMandatoryEntry(0x0028,0x0100,"16");
+      gdcmWarningMacro("(0028,0100) changed from "
+         << nbBitsAllocated << " to 16 for consistency purpose");
+      nbBitsAllocated = 16; 
+   }
+   // check 'Bits Stored' vs 'Bits Allocated'   
+   int nbBitsStored = FileInternal->GetBitsStored();
+   if ( nbBitsStored == 0 || nbBitsStored > nbBitsAllocated )
+   {
+      s.str("");
+      s << nbBitsAllocated;
+      CopyMandatoryEntry(0x0028,0x0101,s.str());
+      gdcmWarningMacro("(0028,0101) changed from "
+                       << nbBitsStored << " to " << nbBitsAllocated
+                       << " for consistency purpose" );
+      nbBitsStored = nbBitsAllocated; 
+    }
+   // check 'Hight Bit Position' vs 'Bits Allocated' and 'Bits Stored'
+   int highBitPosition = FileInternal->GetHighBitPosition();
+   if ( highBitPosition == 0 || 
+        highBitPosition > nbBitsAllocated-1 ||
+        highBitPosition < nbBitsStored-1  )
+   {
+      s.str("");
+      s << nbBitsStored - 1; 
+      CopyMandatoryEntry(0x0028,0x0102,s.str());
+      gdcmWarningMacro("(0028,0102) changed from "
+                       << highBitPosition << " to " << nbBitsAllocated-1
+                       << " for consistency purpose");
+   }
+
+   std::string pixelSpacing = FileInternal->GetEntryValue(0x0028,0x0030);
+   if ( pixelSpacing == GDCM_UNFOUND )
+   {
+      pixelSpacing = "1.0\\1.0";
+       // if missing, Pixel Spacing forced to "1.0\1.0"
+      CopyMandatoryEntry(0x0028,0x0030,pixelSpacing);
+   }
+   std::string imageOrientationPatient = FileInternal->GetEntryValue(0x0020,0x0037);
+   if ( imageOrientationPatient == GDCM_UNFOUND )
+   {
+      imageOrientationPatient = "1\\0\\0\\0\\1\\0";
+      CopyMandatoryEntry(0x0020,0x0037,imageOrientationPatient);
+   }
+   
+   // 'Imager Pixel Spacing' : defaulted to 'Pixel Spacing'
+   // --> This one is the *legal* one !
+   // FIXME : we should write it only when we are *sure* the image comes from
+   //         an imager (see also 0008,0x0064)          
+   CheckMandatoryEntry(0x0018,0x1164,pixelSpacing);
+   
+   // Samples Per Pixel (type 1) : default to grayscale 
+   CheckMandatoryEntry(0x0028,0x0002,"1");
+
+   // --- Check UID-related Entries ---
+
+   // If 'SOP Class UID' exists ('true DICOM' image)
+   // we create the 'Source Image Sequence' SeqEntry
+   // to hold informations about the Source Image
+
+   ValEntry *e_0008_0016 = FileInternal->GetValEntry(0x0008, 0x0016);
+   if ( e_0008_0016 )
+   {
+      // Create 'Source Image Sequence' SeqEntry
+      SeqEntry *sis = new SeqEntry (
+            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x2112) );
+      SQItem *sqi = new SQItem(1);
+      // (we assume 'SOP Instance UID' exists too) 
+      // create 'Referenced SOP Class UID'
+      ValEntry *e_0008_1150 = new ValEntry(
+            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1150) );
+      e_0008_1150->SetValue( e_0008_0016->GetValue());
+      sqi->AddEntry(e_0008_1150);
+      
+      // create 'Referenced SOP Instance UID'
+      ValEntry *e_0008_0018 = FileInternal->GetValEntry(0x0008, 0x0018);
+      ValEntry *e_0008_1155 = new ValEntry(
+            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1155) );
+      e_0008_1155->SetValue( e_0008_0018->GetValue());
+      sqi->AddEntry(e_0008_1155);
+
+      sis->AddSQItem(sqi,1); 
+      // temporarily replaces any previous 'Source Image Sequence' 
+      Archive->Push(sis);
+ 
+      // 'Image Type' (The written image is no longer an 'ORIGINAL' one)
+      CopyMandatoryEntry(0x0008,0x0008,"DERIVED\\PRIMARY");
+   } 
+   else
+   {
+      // There was no 'SOP Class UID'.
+      // the source image was NOT a true Dicom one.
+      // We consider the image is a 'Secondary Capture' one
+      // SOP Class UID
+      e_0008_0016  =  new ValEntry( 
+            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0016) );
+      // [Secondary Capture Image Storage]
+      e_0008_0016 ->SetValue("1.2.840.10008.5.1.4.1.1.7"); 
+      Archive->Push(e_0008_0016); 
+   }
+
+   // ---- The user will never have to take any action on the following ----
+
+   // new value for 'SOP Instance UID'
+   //ValEntry *e_0008_0018 = new ValEntry(
+   //      Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x0018) );
+   //e_0008_0018->SetValue( Util::CreateUniqueUID() );
+   //Archive->Push(e_0008_0018);
+
+   // Instance Creation Date
+   const std::string &date = Util::GetCurrentDate();
+   CopyMandatoryEntry(0x0008,0x0012,date);
+ 
+   // Instance Creation Time
+   const std::string &time = Util::GetCurrentTime();
+   CopyMandatoryEntry(0x0008,0x0013,time);
+
+   // Study Date
+   CheckMandatoryEntry(0x0008,0x0020,date);
+   // Study Time
+   CheckMandatoryEntry(0x0008,0x0030,time);
+
+   // Accession Number
+   //CopyMandatoryEntry(0x0008,0x0050,"");
+   CheckMandatoryEntry(0x0008,0x0050,"");
+   
+
+   // ----- Add Mandatory Entries if missing ---
+   // Entries whose type is 1 are mandatory, with a mandatory value
+   // Entries whose type is 1c are mandatory-inside-a-Sequence,
+   //                          with a mandatory value
+   // Entries whose type is 2 are mandatory, with an optional value
+   // Entries whose type is 2c are mandatory-inside-a-Sequence,
+   //                          with an optional value
+   // Entries whose type is 3 are optional
+
+   // 'Study Instance UID'
+   // Keep the value if exists
+   // The user is allowed to create his own Study, 
+   //          keeping the same 'Study Instance UID' for various images
+   // The user may add images to a 'Manufacturer Study',
+   //          adding new Series to an already existing Study 
+   CheckMandatoryEntry(0x0020,0x000d,Util::CreateUniqueUID());
+
+   // 'Serie Instance UID'
+   // Keep the value if exists
+   // The user is allowed to create his own Series, 
+   // keeping the same 'Serie Instance UID' for various images
+   // The user shouldn't add any image to a 'Manufacturer Serie'
+   // but there is no way no to prevent him for doing that 
+   CheckMandatoryEntry(0x0020,0x000e,Util::CreateUniqueUID());
+
+   // Study ID
+   CheckMandatoryEntry(0x0020,0x0010,"");
+
+   // Series Number
+   CheckMandatoryEntry(0x0020,0x0011,"");
+
+   // Instance Number
+   CheckMandatoryEntry(0x0020,0x0013,"");
+  
+   // Patient Orientation    
+   // Can be computed from (0020|0037) :  Image Orientation (Patient)    
+   gdcm::Orientation o;    
+   std::string ori = o.GetOrientation ( FileInternal );    
+   if (ori != "\\" && ori != GDCM_UNFOUND)    
+      CheckMandatoryEntry(0x0020,0x0020,ori);    
+   else    
+      CheckMandatoryEntry(0x0020,0x0020,"");
+
+   // Modality : if missing we set it to 'OTher'
+   CheckMandatoryEntry(0x0008,0x0060,"OT");
+
+   // Manufacturer : if missing we set it to 'GDCM Factory'
+   CheckMandatoryEntry(0x0008,0x0070,"GDCM Factory");
+
+   // Institution Name : if missing we set it to 'GDCM Hospital'
+   CheckMandatoryEntry(0x0008,0x0080,"GDCM Hospital");
+
+   // Patient's Name : if missing, we set it to 'GDCM^Patient'
+   CheckMandatoryEntry(0x0010,0x0010,"GDCM^Patient");
+
+   // Patient ID
+   CheckMandatoryEntry(0x0010,0x0020,"");
+
+   // Patient's Birth Date : 'type 2' entry -> must exist, value not mandatory
+   CheckMandatoryEntry(0x0010,0x0030,"");
+
+   // Patient's Sex :'type 2' entry -> must exist, value not mandatory
+   CheckMandatoryEntry(0x0010,0x0040,"");
+
+   // Referring Physician's Name :'type 2' entry -> must exist, value not mandatory
+   CheckMandatoryEntry(0x0008,0x0090,"");
+
+} 
+
+void FileHelper::CheckMandatoryEntry(uint16_t group,uint16_t elem,std::string value)
+{
+   ValEntry *ve = FileInternal->GetValEntry(group, elem);
+   if ( !ve)
+   {
+      ve = new ValEntry(
+            Global::GetDicts()->GetDefaultPubDict()->GetEntry(group, elem) );
+      ve->SetValue( value );
+      Archive->Push(ve);
+   }
+}
+
+void FileHelper::CopyMandatoryEntry(uint16_t group,uint16_t elem,std::string value)
+{
+   ValEntry *entry = CopyValEntry(group,elem);
+   entry->SetValue(value);
+   Archive->Push(entry);
+}
+
+/**
+ * \brief Restore in the File the initial group 0002
+ */
+void FileHelper::RestoreWriteMandatory()
+{
+   // group 0002 may be pushed out for ACR-NEMA writting purposes 
+   Archive->Restore(0x0002,0x0000);
+   Archive->Restore(0x0002,0x0001);
+   Archive->Restore(0x0002,0x0002);
+   Archive->Restore(0x0002,0x0003);
+   Archive->Restore(0x0002,0x0010);
+   Archive->Restore(0x0002,0x0012);
+   Archive->Restore(0x0002,0x0013);
+   Archive->Restore(0x0002,0x0016);
+   Archive->Restore(0x0002,0x0100);
+   Archive->Restore(0x0002,0x0102);
+
+   Archive->Restore(0x0008,0x0012);
+   Archive->Restore(0x0008,0x0013);
+   Archive->Restore(0x0008,0x0016);
+   Archive->Restore(0x0008,0x0018);
+   Archive->Restore(0x0008,0x0060);
+   Archive->Restore(0x0008,0x0070);
+   Archive->Restore(0x0008,0x0080);
+   Archive->Restore(0x0008,0x0090);
+   Archive->Restore(0x0008,0x2112);
+
+   Archive->Restore(0x0010,0x0010);
+   Archive->Restore(0x0010,0x0030);
+   Archive->Restore(0x0010,0x0040);
+
+   Archive->Restore(0x0020,0x000d);
+   Archive->Restore(0x0020,0x000e);
+
+}
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \brief Factorization for various forms of constructors.
+ */
+void FileHelper::Initialize()
+{
+   UserFunction = 0;
+   KeepMediaStorageSOPClassUID = false;
+
+   WriteMode = WMODE_RAW;
+   WriteType = ExplicitVR;
+
+   PixelReadConverter  = new PixelReadConvert;
+   PixelWriteConverter = new PixelWriteConvert;
+   Archive = new DocEntryArchive( FileInternal );
+}
+
+/**
+ * \brief Reads/[decompresses] the pixels, 
+ *        *without* making RGB from Palette Colors 
+ * @return the pixels area, whatever its type 
+ *         (uint8_t is just for prototyping : feel free to Cast it) 
+ */ 
+uint8_t *FileHelper::GetRaw()
+{
+   PixelReadConverter->SetUserFunction( UserFunction );
+
+   uint8_t *raw = PixelReadConverter->GetRaw();
+   if ( ! raw )
+   {
+      // The Raw image migth not be loaded yet:
+      std::ifstream *fp = FileInternal->OpenFile();
+      PixelReadConverter->ReadAndDecompressPixelData( fp );
+      if ( fp ) 
+         FileInternal->CloseFile();
+
+      raw = PixelReadConverter->GetRaw();
+      if ( ! raw )
+      {
+         gdcmWarningMacro( "Read/decompress of pixel data apparently went wrong.");
+         return 0;
+      }
+   }
+   return raw;
+}
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief   Prints the common part of ValEntry, BinEntry, SeqEntry
+ * @param   os ostream we want to print in
+ * @param indent (unused)
+ */
+void FileHelper::Print(std::ostream &os, std::string const &)
+{
+   FileInternal->SetPrintLevel(PrintLevel);
+   FileInternal->Print(os);
+
+   if ( FileInternal->IsReadable() )
+   {
+      PixelReadConverter->SetPrintLevel(PrintLevel);
+      PixelReadConverter->Print(os);
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmFileHelper.h b/Utilities/ITK/Utilities/gdcm/src/gdcmFileHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..be8cd180f0d8c815ac092bbeb75fa6008b56022e
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmFileHelper.h
@@ -0,0 +1,234 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmFileHelper.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMFILEHELPER_H
+#define GDCMFILEHELPER_H
+
+#include "gdcmDebug.h"
+#include "gdcmBase.h"
+
+
+
+namespace gdcm 
+{
+class File;
+class ValEntry;
+class BinEntry;
+class SeqEntry;
+class PixelReadConvert;
+class PixelWriteConvert;
+class DocEntryArchive;
+
+typedef void (*VOID_FUNCTION_PUINT8_PFILE_POINTER)(uint8_t *, File *);
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief In addition to Dicom header exploration, this class is designed
+ * for accessing the image/volume content. One can also use it to
+ * write Dicom/ACR-NEMA/RAW files.
+ */
+class GDCM_EXPORT FileHelper : public Base
+{
+public:
+   enum FileMode
+   {
+      WMODE_RAW,
+      WMODE_RGB
+   };
+     
+public:
+   FileHelper( );
+   FileHelper( File *header );
+   GDCM_LEGACY(FileHelper( std::string const &filename ));
+   
+   virtual ~FileHelper();
+
+   void Print(std::ostream &os = std::cout, std::string const &indent = ""); 
+
+   /// Accessor to \ref File
+   File *GetFile() { return FileInternal; }
+   
+
+   void SetLoadMode(int loadMode);
+   void SetFileName(std::string const &fileName);
+   bool Load();
+   /// to allow user to modify pixel order (e.g. Mirror, TopDown,...)
+   void SetUserFunction( VOID_FUNCTION_PUINT8_PFILE_POINTER userFunc ) 
+                        { UserFunction = userFunc; }   
+   // File methods
+   bool SetValEntry(std::string const &content,
+                    uint16_t group, uint16_t elem);
+   bool SetBinEntry(uint8_t *content, int lgth,
+                    uint16_t group, uint16_t elem);
+
+   ValEntry *InsertValEntry(std::string const &content,
+                            uint16_t group, uint16_t elem);
+   BinEntry *InsertBinEntry(uint8_t *binArea, int lgth,
+                            uint16_t group, uint16_t elem);
+   SeqEntry *InsertSeqEntry(uint16_t group, uint16_t elem);
+
+   // File helpers
+   size_t GetImageDataSize();
+   size_t GetImageDataRawSize();
+
+   uint8_t *GetImageData();
+   uint8_t *GetImageDataRaw();
+
+   GDCM_LEGACY(size_t GetImageDataIntoVector(void *destination,size_t maxSize));
+
+   void SetImageData(uint8_t *data, size_t expectedSize);
+
+   // User data
+   void SetUserData(uint8_t *data, size_t expectedSize);
+   uint8_t *GetUserData();
+   size_t GetUserDataSize();
+   // RBG data (from file)
+   uint8_t *GetRGBData();
+   size_t GetRGBDataSize();
+   // RAW data (from file)
+   uint8_t *GetRawData();
+   size_t GetRawDataSize();
+
+   // LUT
+   uint8_t* GetLutRGBA();
+   int GetLutItemNumber();
+   int GetLutItemSize();
+
+   // Write mode
+
+   /// \brief Tells the writer we want to keep 'Grey pixels + Palettes color'
+   ///        when possible (as opposed to convert 'Palettes color' to RGB)
+   void SetWriteModeToRaw()           { SetWriteMode(WMODE_RAW);  }
+   /// \brief Tells the writer we want to write RGB image when possible
+   ///        (as opposed to 'Grey pixels + Palettes color')
+   void SetWriteModeToRGB()           { SetWriteMode(WMODE_RGB);  }
+   /// \brief Sets the Write Mode ( )
+   void SetWriteMode(FileMode mode)   { WriteMode = mode;         }
+   /// \brief Gets the Write Mode ( )
+   FileMode GetWriteMode()            { return WriteMode;         }
+
+   // Write format
+
+   /// \brief Tells the writer we want to write as Implicit VR
+   void SetWriteTypeToDcmImplVR()     { SetWriteType(ImplicitVR); }
+   /// \brief Tells the writer we want to write as Explicit VR
+   void SetWriteTypeToDcmExplVR()     { SetWriteType(ExplicitVR); }
+   /// \brief Tells the writer we want to write as ACR-NEMA
+   void SetWriteTypeToAcr()           { SetWriteType(ACR);        }
+   /// \brief Tells the writer we want to write as LibIDO
+   void SetWriteTypeToAcrLibido()     { SetWriteType(ACR_LIBIDO); }
+   /// \brief Tells the writer we want to write as JPEG   
+   void SetWriteTypeToJPEG()          { SetWriteType(JPEG);       }
+   /// \brief Tells the writer which format we want to write
+   /// (ImplicitVR, ExplicitVR, ACR, ACR_LIBIDO)
+   void SetWriteType(FileType format) { WriteType = format;       }
+   /// \brief Gets the format we talled the write we wanted to write
+   /// (ImplicitVR, ExplicitVR, ACR, ACR_LIBIDO)
+   FileType GetWriteType()            { return WriteType;         }
+
+   // Write pixels of ONE image on hard drive
+   // No test is made on processor "endianness"
+   // The user must call his reader correctly
+   bool WriteRawData  (std::string const &fileName);
+   bool WriteDcmImplVR(std::string const &fileName);
+   bool WriteDcmExplVR(std::string const &fileName);
+   bool WriteAcr      (std::string const &fileName);
+   bool Write         (std::string const &fileName);
+   /// \brief if user knows he didn't modify the pixels (e.g. he just anonymized 
+   ///        the file), he is allowed to ask to keep the original
+   ///        'Media Storage SOP Class UID' and 'Image Type'   
+   void SetKeepMediaStorageSOPClassUID (bool v) 
+                              { KeepMediaStorageSOPClassUID = v; }
+   // no GetKeepMediaStorageSOPClassUID() method, on purpose!
+
+protected:
+   bool CheckWriteIntegrity();
+
+   void SetWriteToRaw();
+   void SetWriteToRGB();
+   void RestoreWrite();
+
+   void SetWriteFileTypeToACR();
+   void SetWriteFileTypeToJPEG();
+   void SetWriteFileTypeToExplicitVR();
+   void SetWriteFileTypeToImplicitVR();
+   void RestoreWriteFileType();
+
+   void SetWriteToLibido();
+   void SetWriteToNoLibido();
+   void RestoreWriteOfLibido();
+
+   ValEntry *CopyValEntry(uint16_t group, uint16_t elem);
+   BinEntry *CopyBinEntry(uint16_t group, uint16_t elem, 
+                          const std::string &vr);
+   void CheckMandatoryElements();
+   void CheckMandatoryEntry(uint16_t group, uint16_t elem,std::string value);
+   void CopyMandatoryEntry(uint16_t group, uint16_t elem,std::string value);
+   void RestoreWriteMandatory();
+
+private:
+   void Initialize();
+
+   uint8_t *GetRaw();
+
+// members variables:
+   /// gdcm::File to use to load the file
+   File *FileInternal;
+
+   /// \brief Whether the underlying \ref gdcm::File was loaded by
+   ///  the constructor or passed to the constructor. 
+   ///  When false the destructor is in charge of deletion.
+   bool SelfHeader;
+   
+   /// Whether already parsed or not
+   bool Parsed;
+
+   // Utility pixel converter
+   /// \brief Pointer to the PixelReadConverter
+   PixelReadConvert *PixelReadConverter;
+   /// \brief Pointer to the PixelWriteConverter
+   PixelWriteConvert *PixelWriteConverter;
+
+   // Utility header archive
+   /// \brief Pointer to the DocEntryArchive (used while writting process)
+   DocEntryArchive *Archive;
+
+   // Write variables
+   /// \brief (WMODE_RAW, WMODE_RGB)
+   FileMode WriteMode;
+
+   /// \brief (ImplicitVR, ExplicitVR, ACR, ACR_LIBIDO)
+   FileType WriteType;
+
+   /// \brief Pointer to a user supplied function to allow modification of pixel order
+   /// (i.e. : Mirror, TopDown, 90�Rotation, ...)
+   /// use as : void userSuppliedFunction(uint8_t *im, gdcm::File *f)
+   /// NB : the "uint8_t *" type of first param is just for prototyping.
+   /// User will Cast it according what he founds with f->GetPixelType()
+   /// See vtkgdcmSerieViewer for an example
+   VOID_FUNCTION_PUINT8_PFILE_POINTER UserFunction;
+   
+   /// \brief if user knows he didn't modify the pixels (e.g. he just 
+   /// anonymized the file), he is allowed to ask to keep the original
+   /// 'Media Storage SOP Class UID' and 'Image Type'  
+   bool KeepMediaStorageSOPClassUID;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmGlobal.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmGlobal.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b477c458e9035f33ea54585b85f9ebad083f9a30
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmGlobal.cxx
@@ -0,0 +1,141 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmGlobal.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.5 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmGlobal.h"
+
+#include "gdcmDebug.h"
+#include "gdcmVR.h"
+#include "gdcmTS.h"
+#include "gdcmDictGroupName.h"
+#include "gdcmDictSet.h"
+#include "gdcmDicomDirElement.h"
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/// \brief Those global string that are returned by reference everywhere in 
+/// gdcm code used to be in gdcmCommon.h but due to a 'bug' in gcc/MacOSX
+/// you cannot have static initialization in a multithreaded environment
+/// since there is a lazy construction everything got skrew up somehow
+/// Therefore the actual initialization is done in a cxx file (avoid
+/// duplicated symbol), and an extern is used in gdcmCommon.h
+
+const std::string GDCM_UNKNOWN   = "gdcm::Unknown";
+const std::string GDCM_UNFOUND   = "gdcm::Unfound";
+const std::string GDCM_BINLOADED = "gdcm::Binary data loaded";
+const std::string GDCM_NOTLOADED = "gdcm::NotLoaded";
+const std::string GDCM_UNREAD    = "gdcm::UnRead";
+const std::string GDCM_NOTASCII  = "gdcm::NotAscii";
+const std::string GDCM_PIXELDATA = "gdcm::Pixel Data to be loaded";
+//-----------------------------------------------------------------------------
+DictSet         *Global::Dicts     = (DictSet *)0;
+VR              *Global::ValRes    = (VR *)0;
+TS              *Global::TranSyn   = (TS *)0;
+DictGroupName   *Global::GroupName = (DictGroupName *)0;
+DicomDirElement *Global::ddElem    = (DicomDirElement *)0;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief   Global container
+ */
+Global Glob;
+
+//-------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   constructor : populates the various H Tables
+ */
+Global::Global()
+{
+   if (ValRes || TranSyn || Dicts || ddElem)
+   {
+      gdcmWarningMacro( "VR or TS or Dicts already allocated");
+      return;
+   }
+   Dicts     = new DictSet();
+   ValRes    = new VR();
+   TranSyn   = new TS();
+   GroupName = new DictGroupName();
+   ddElem    = new DicomDirElement();
+}
+
+/**
+ * \brief   canonical destructor 
+ */
+Global::~Global()
+{
+   delete Dicts;
+   delete ValRes;
+   delete TranSyn;
+   delete GroupName;
+   delete ddElem;
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   returns a pointer to Dictionaries Table 
+ */
+DictSet *Global::GetDicts()
+{
+   return Dicts;
+}
+
+/**
+ * \brief   returns a pointer to the 'Value Representation Table' 
+ */
+VR *Global::GetVR()
+{
+   return ValRes;
+}
+
+/**
+ * \brief   returns a pointer to the 'Transfer Syntax Table' 
+ */
+TS *Global::GetTS()
+{
+   return TranSyn;
+}
+
+/**
+ * \brief   returns a pointer to the Group name correspondance table
+ */
+DictGroupName *Global::GetDictGroupName()
+{
+   return GroupName;
+}
+
+/**
+ * \brief   returns a pointer to the DicomDir related elements Table 
+ */
+DicomDirElement *Global::GetDicomDirElements()
+{
+   return ddElem;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmGlobal.h b/Utilities/ITK/Utilities/gdcm/src/gdcmGlobal.h
new file mode 100644
index 0000000000000000000000000000000000000000..addcc9540c6e63f77136221cca3308f7ee8311ae
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmGlobal.h
@@ -0,0 +1,66 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmGlobal.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMGLOBAL_H
+#define GDCMGLOBAL_H
+
+#include "gdcmCommon.h"
+
+namespace gdcm 
+{
+class DictSet;
+class VR;
+class TS;
+class DictGroupName;
+class DicomDirElement;
+//-----------------------------------------------------------------------------
+/**
+ * \brief   This class contains all globals elements that might be
+ *          instanciated only once (singletons).
+ */
+class GDCM_EXPORT Global
+{
+public:
+   Global();
+   ~Global();
+
+   static DictSet *GetDicts();
+   static VR *GetVR();
+   static TS *GetTS();
+   static DictGroupName *GetDictGroupName();
+   static DicomDirElement *GetDicomDirElements();
+
+private:
+   /// Pointer to a container, holding _all_ the Dicom Dictionaries.
+   static DictSet *Dicts;
+   /// Pointer to a hash table containing the 'Value Representations'.
+   static VR *ValRes;
+   /// \brief Pointer to a hash table containing the Transfer Syntax codes 
+   ///        and their english description 
+   static TS *TranSyn; 
+   /// \brief Pointer to a hash table containing the Group codes 
+   ///        and their english name (from NIH) 
+   static DictGroupName *GroupName; 
+   /// \brief Pointer to the hash table containing the Dicom Elements necessary 
+   ///        to describe each part of a DICOMDIR 
+   static DicomDirElement *ddElem;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragment.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragment.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..502f8554ca7a2f21f001b4b7d732ff1a53de2f2b
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragment.cxx
@@ -0,0 +1,112 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmJPEGFragment.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+                                                                                
+#include "gdcmJPEGFragment.h"
+#include "gdcmDebug.h"
+
+namespace gdcm
+{
+//-------------------------------------------------------------------------
+// For JPEG 2000, body in file gdcmJpeg2000.cxx
+// Not yet made
+bool gdcm_read_JPEG2000_file (std::ifstream *fp, void *image_buffer);
+
+// For JPEG-LS, body in file gdcmJpegLS.cxx
+// Not yet made
+bool gdcm_read_JPEGLS_file (std::ifstream *fp, void *image_buffer);
+
+//-------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief Default constructor.
+ */
+JPEGFragment::JPEGFragment()
+{
+   Offset = 0;
+   Length = 0;
+
+   pImage = 0;
+
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief Decompress 8bits JPEG Fragment
+ * @param fp ifstream to write to
+ * @param buffer     output (data decompress)
+ * @param nBits      8/12 or 16 bits jpeg
+ * @param statesuspension state suspension
+ */
+void JPEGFragment::DecompressJPEGFramesFromFile(std::ifstream *fp,
+                                                uint8_t *buffer, int nBits, 
+                                                int &statesuspension)
+{
+   // First thing need to reset file to proper position:
+   fp->seekg( Offset, std::ios::beg);
+
+   if ( nBits == 8 )
+   {
+      // JPEG Lossy : call to IJG 6b - 8 bits
+      ReadJPEGFile8( fp, buffer, statesuspension);
+   }
+   else if ( nBits <= 12 )
+   {
+      // JPEG Lossy : call to IJG 6b - 12 bits
+      ReadJPEGFile12 ( fp, buffer, statesuspension);
+   }
+   else if ( nBits <= 16 )
+   {
+      // JPEG Lossy : call to IJG 6b - 16 bits
+      ReadJPEGFile16 ( fp, buffer, statesuspension);
+      //gdcmAssertMacro( IsJPEGLossless );
+   }
+   else
+   {
+      // FIXME : only the bits number is checked,
+      //         NOT the compression method
+
+      // other JPEG lossy not supported
+      gdcmErrorMacro( "Unknown jpeg lossy compression ");
+   }
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief        Print self.
+ * @param os     Stream to print to.
+ * @param indent Indentation string to be prepended during printing.
+ */
+void JPEGFragment::Print( std::ostream &os, std::string const &indent )
+{
+   os << indent
+      << "JPEG fragment: offset : " <<  Offset
+      << "   length : " <<  Length
+      << std::endl;
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragment.h b/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragment.h
new file mode 100644
index 0000000000000000000000000000000000000000..800e29d4762ded11e3ae18cf2b8e115badeb28a9
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragment.h
@@ -0,0 +1,70 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmJPEGFragment.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+
+#ifndef GDCMJPEGFRAGMENT_H
+#define GDCMJPEGFRAGMENT_H
+
+#include "gdcmCommon.h"
+
+#include <iostream>
+#include <fstream>
+
+namespace gdcm 
+{
+/**
+ * \brief *very* internal class . Shouldn't appear here !
+ *         Utility class for summerizing the informations of a JPEG
+ *        fragment of an "Encapsulated JPEG Compressed Image".
+ *        This information is a mix of:
+ *        - the fragment offset
+ *        - the fragment length 
+ *
+ *        Each instance of this class (they can be as many instances for
+ *        a given Document as they are JPEG fragments and they are
+ *        collected in a \ref JPEGFragmentsInfo )
+ */
+class GDCM_EXPORT JPEGFragment
+{
+public:
+   JPEGFragment();
+   void Print( std::ostream &os = std::cout, std::string const &indent = "" );
+   void DecompressJPEGFramesFromFile(std::ifstream *fp, 
+                                     uint8_t *buffer, int nBits, 
+                                     int &statesuspension);
+
+   bool ReadJPEGFile8  (std::ifstream *fp, void *image_buffer, int &statesuspension );
+   bool ReadJPEGFile12 (std::ifstream *fp, void *image_buffer, int &statesuspension );
+   bool ReadJPEGFile16 (std::ifstream *fp, void *image_buffer, int &statesuspension );
+
+   void SetLength(uint32_t length) { Length = length; }
+   uint32_t GetLength()            { return Length;   }
+   void SetOffset(uint32_t offset) { Offset = offset; }
+   uint32_t GetOffset()            { return Offset;   }
+   uint8_t *GetImage()             { return pImage;   }
+
+private:
+   uint32_t Offset;
+   uint32_t Length;
+
+   uint8_t *pImage;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragmentsInfo.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragmentsInfo.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..62418cbfd6627791180a67081a9d711cb8f8b0a1
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragmentsInfo.cxx
@@ -0,0 +1,129 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmJPEGFragmentsInfo.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmJPEGFragmentsInfo.h"
+#include "gdcmDebug.h"
+
+#include <fstream>
+
+namespace gdcm 
+{
+//-------------------------------------------------------------------------
+// Constructor / Destructor
+JPEGFragmentsInfo::JPEGFragmentsInfo()
+{
+   StateSuspension = 0;
+}
+
+/**
+ * \brief Default destructor
+ */
+JPEGFragmentsInfo::~JPEGFragmentsInfo()
+{
+   for(JPEGFragmentsList::iterator it  = Fragments.begin();
+                                   it != Fragments.end();
+                                 ++it )
+   {
+      delete *it;
+   }
+   Fragments.clear();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+void JPEGFragmentsInfo::DecompressFromFile(std::ifstream *fp, uint8_t *buffer, int nBits, int , int )
+{
+   // Pointer to the Raw image
+   uint8_t *localRaw = buffer;
+
+  // Loop on the fragment[s]
+   JPEGFragmentsList::const_iterator it;
+   for( it  = Fragments.begin();
+        it != Fragments.end();
+        ++it )
+   {
+     (*it)->DecompressJPEGFramesFromFile(fp, localRaw, nBits, StateSuspension);
+     // update pointer to image after some scanlines read:
+     localRaw = (*it)->GetImage();
+   }
+}
+
+void JPEGFragmentsInfo::AddFragment(JPEGFragment *fragment)
+{
+   Fragments.push_back(fragment);
+}
+
+JPEGFragment *JPEGFragmentsInfo::GetFirstFragment()
+{
+   ItFragments = Fragments.begin();
+   if (ItFragments != Fragments.end())
+      return  *ItFragments;
+   return NULL;
+}
+
+JPEGFragment *JPEGFragmentsInfo::GetNextFragment()
+{
+   gdcmAssertMacro (ItFragments != Fragments.end());
+
+   ++ItFragments;
+   if (ItFragments != Fragments.end())
+      return  *ItFragments;
+   return NULL;
+}
+
+unsigned int JPEGFragmentsInfo::GetFragmentCount()
+{
+   return Fragments.size();
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief        Print self.
+ * @param os     Stream to print to.
+ * @param indent Indentation string to be prepended during printing.
+ */
+void JPEGFragmentsInfo::Print( std::ostream &os, std::string const &indent )
+{
+   os << std::endl;
+   os << indent
+      << "----------------- JPEG fragments --------------------------------"
+      << std::endl << std::endl;
+   os << indent
+      << "Total number of fragments : " << Fragments.size()
+      << std::endl;
+   int fragmentNumber = 0;
+   for(JPEGFragmentsList::iterator it  = Fragments.begin();
+                                   it != Fragments.end();
+                                 ++it)
+   {
+      os << indent
+         << "   fragment number :" << fragmentNumber++;
+      (*it)->Print( os, indent + "   ");
+   }
+   os << std::endl;
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragmentsInfo.h b/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragmentsInfo.h
new file mode 100644
index 0000000000000000000000000000000000000000..c6eac97018375e9ececc7359f8fae29461ecc3b5
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmJPEGFragmentsInfo.h
@@ -0,0 +1,71 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmJPEGFragmentsInfo.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+
+#ifndef GDCMJPEGFRAGMENTSINFO_H
+#define GDCMJPEGFRAGMENTSINFO_H
+
+#include "gdcmJPEGFragment.h"
+
+#include <list>
+#include <iostream>
+
+namespace gdcm 
+{
+/**
+ * \brief Utility class for gathering the informations of the collection
+ *        of JPEG fragment[s] (see \ref JPEGFragment)  when handling
+ *        "Encapsulated JPEG Compressed Images". 
+ *        The informations on each frame are obtained during the pixel parsing
+ *        of a gdcm::File (refer to \ref File::ComputeJPEGFragmentInfo() ).
+ *        They shall be used when (if necessary) decoding the fragments.
+ *
+ *        This class is simply a stl list<> of \ref JPEGFragment.
+ */
+class GDCM_EXPORT JPEGFragmentsInfo
+{
+friend class File;
+friend class PixelReadConvert;
+
+private:
+   JPEGFragmentsInfo();
+   ~JPEGFragmentsInfo();
+   void Print( std::ostream &os = std::cout, std::string const &indent = "" );
+
+   void DecompressFromFile(std::ifstream *fp, uint8_t *buffer, int nBits,
+                           int numBytes, int length);
+
+   void AddFragment(JPEGFragment *fragment);
+   JPEGFragment *GetFirstFragment();
+   JPEGFragment *GetNextFragment();
+   unsigned int GetFragmentCount();
+
+   typedef std::list<JPEGFragment *> JPEGFragmentsList;
+
+    //Some mathieu hack:
+   int StateSuspension;
+   void *SampBuffer;
+   char *pimage;
+   JPEGFragmentsList Fragments;
+   JPEGFragmentsList::iterator ItFragments;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8d6eab3a265b27e52c5c6add6fc2d998b9204536
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg.cxx
@@ -0,0 +1,379 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmJpeg.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.7 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+#include "gdcmFileHelper.h"
+#include "gdcmJPEGFragment.h"
+#include "gdcmDebug.h"
+
+#if defined(__sgi) && !defined(__GNUC__)
+// Try to get rid of the warning:
+//cc-3505 CC: WARNING File = /usr/include/internal/setjmp_core.h, Line = 74
+//  setjmp not marked as unknown_control_flow because it is not declared as a
+//          function
+//
+//  #pragma unknown_control_flow (setjmp)
+#  if   (_COMPILER_VERSION >= 730)
+#  pragma set woff 3505
+#  endif
+#endif
+#ifdef _MSC_VER
+// Let us get rid of this funny warning on /W4:
+// warning C4611: interaction between '_setjmp' and C++ object
+// destruction is non-portable
+#pragma warning( disable : 4611 )
+#endif
+
+#include <setjmp.h>
+#include <fstream>
+
+#if defined(__BORLANDC__)
+   #include <mem.h> // for memset
+#endif 
+
+#include "jdatasrc.cxx"
+#include "jdatadst.cxx"
+
+namespace gdcm 
+{
+
+ /**
+ * \brief   routine for JPEG decompression 
+ * @param fp pointer to an already open file descriptor 
+ *                      8 significant bits per pixel
+ * @param im_buf Points to array (of R,G,B-order) data to compress
+ * @param quality compression quality
+ * @param image_height Number of rows in image 
+ * @param image_width Number of columns in image
+ * @return 1 on success, 0 on error
+ */
+ 
+bool gdcm_write_JPEG_file (std::ostream *fp, void *im_buf, 
+                           int image_width, int image_height, int quality)
+{
+
+   JSAMPLE *image_buffer = (JSAMPLE*) im_buf;
+
+  /* This struct contains the JPEG compression parameters and pointers to
+   * working space (which is allocated as needed by the JPEG library).
+   * It is possible to have several such structures, representing multiple
+   * compression/decompression processes, in existence at once.  We refer
+   * to any one struct (and its associated working data) as a "JPEG object".
+   */
+  struct jpeg_compress_struct cinfo;
+  /* This struct represents a JPEG error handler.  It is declared separately
+   * because applications often want to supply a specialized error handler
+   * (see the second half of this file for an example).  But here we just
+   * take the easy way out and use the standard error handler, which will
+   * print a message on stderr and call exit() if compression fails.
+   * Note that this struct must live as long as the main JPEG parameter
+   * struct, to avoid dangling-pointer problems.
+   */
+  struct jpeg_error_mgr jerr;
+  /* More stuff */
+  //FILE*  outfile;    /* target FILE* /
+  JSAMPROW row_pointer[1];   /* pointer to JSAMPLE row[s] */
+  int row_stride;            /* physical row width in image buffer */
+
+  /* Step 1: allocate and initialize JPEG compression object */
+
+  /* We have to set up the error handler first, in case the initialization
+   * step fails.  (Unlikely, but it could happen if you are out of memory.)
+   * This routine fills in the contents of struct jerr, and returns jerr's
+   * address which we place into the link field in cinfo.
+   */
+  cinfo.err = jpeg_std_error(&jerr);
+  /* Now we can initialize the JPEG compression object. */
+  jpeg_create_compress(&cinfo);
+
+  /* Step 2: specify data destination (eg, a file) */
+  /* Note: steps 2 and 3 can be done in either order. */
+
+  /* Here we use the library-supplied code to send compressed data to a
+   * stdio stream.  You can also write your own code to do something else.
+   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
+   * requires it in order to write binary files.
+   */
+ // if ((outfile = fopen(filename, "wb")) == NULL) {
+ //   fprintf(stderr, "can't open %s\n", filename);
+ //   exit(1);
+ //
+ // }
+  assert( 0 );
+  (void)fp;
+  //jpeg_stdio_dest(&cinfo, fp, 0, 0, image_width, image_height, quality);
+
+  /* Step 3: set parameters for compression */
+
+  /* First we supply a description of the input image.
+   * Four fields of the cinfo struct must be filled in:
+   */
+  cinfo.image_width = image_width;/* image width and height, in pixels */
+  cinfo.image_height = image_height;
+  cinfo.input_components = 3;     /* # of color components per pixel */
+  cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+  /* Now use the library's routine to set default compression parameters.
+   * (You must set at least cinfo.in_color_space before calling this,
+   * since the defaults depend on the source color space.)
+   */
+  jpeg_set_defaults(&cinfo);
+  /* Now you can set any non-default parameters you wish to.
+   * Here we just illustrate the use of quality (quantization table) scaling:
+   */
+  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
+
+  /* Step 4: Start compressor */
+
+  /* TRUE ensures that we will write a complete interchange-JPEG file.
+   * Pass TRUE unless you are very sure of what you're doing.
+   */
+  jpeg_start_compress(&cinfo, TRUE);
+
+  /* Step 5: while (scan lines remain to be written) */
+  /*           jpeg_write_scanlines(...); */
+
+  /* Here we use the library's state variable cinfo.next_scanline as the
+   * loop counter, so that we don't have to keep track ourselves.
+   * To keep things simple, we pass one scanline per call; you can pass
+   * more if you wish, though.
+   */
+  row_stride = image_width * 3;/* JSAMPLEs per row in image_buffer */
+
+  while (cinfo.next_scanline < cinfo.image_height) {
+    /* jpeg_write_scanlines expects an array of pointers to scanlines.
+     * Here the array is only one element long, but you could pass
+     * more than one scanline at a time if that's more convenient.
+     */
+    row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+
+    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+  }
+
+  /* Step 6: Finish compression */
+
+  jpeg_finish_compress(&cinfo);
+  
+  /* After finish_compress, we can close the output file. */
+  
+ // fclose(fp); --> the caller will close (multiframe treatement)
+
+  /* Step 7: release JPEG compression object */
+
+  /* This is an important step since it will release a good deal of memory. */
+  jpeg_destroy_compress(&cinfo);
+
+  /* And we're done! */
+
+  return true;
+}
+
+//-----------------------------------------------------------------------------
+struct my_error_mgr {
+   struct jpeg_error_mgr pub; /* "public" fields */
+   jmp_buf setjmp_buffer;     /* for return to caller */
+};
+typedef struct my_error_mgr* my_error_ptr;
+//-----------------------------------------------------------------------------
+
+/*
+ * Here's the routine that will replace the standard error_exit method:
+ */
+extern "C" {
+METHODDEF(void) my_error_exit (j_common_ptr cinfo) {
+   /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
+   my_error_ptr myerr = (my_error_ptr) cinfo->err;
+
+   /* Always display the message. */
+   /* We could postpone this until after returning, if we chose. */
+   (*cinfo->err->output_message) (cinfo);
+
+   /* Return control to the setjmp point */
+   longjmp(myerr->setjmp_buffer, 1);
+}
+
+//METHODDEF(void) my_output_message (j_common_ptr cinfo)
+//{
+//   char buffer[JMSG_LENGTH_MAX];
+// 
+//   /* Create the message */
+//   (*cinfo->err->format_message) (cinfo, buffer);
+//
+//   // Custom display message, we could be more fancy and throw an exception:
+//   gdcmErrorMacro( buffer );
+//}
+
+}
+//-----------------------------------------------------------------------------
+ 
+/**
+ * \brief   routine for JPEG decompression 
+ * @param fp pointer to an already open file descriptor 
+ *                      8 significant bits per pixel
+ * @param image_buffer to receive uncompressed pixels
+ * @param statesuspension Suspension State basically it should be 3 otherwise more complex to handle
+ * @return 1 on success, 0 on error
+ */
+void *SampBuffer; 
+bool JPEGFragment::ReadJPEGFile (std::ifstream *fp, void *image_buffer, int &statesuspension)
+{
+   pImage = (uint8_t*)image_buffer;
+   // This struct contains the JPEG decompression parameters and pointers to
+   // working space (which is allocated as needed by the JPEG library).
+
+   static struct jpeg_decompress_struct cinfo;
+
+   // -------------- inside, we found :
+   // JDIMENSION image_width;       // input image width 
+   // JDIMENSION image_height;      // input image height 
+   // int input_components;         // nb of color components in input image 
+   // J_COLOR_SPACE in_color_space; // colorspace of input image 
+   // double input_gamma;           // image gamma of input image 
+
+   // We use our private extension JPEG error handler.
+   // Note that this struct must live as long as the main JPEG parameter
+   // struct, to avoid dangling-pointer problems.
+
+   struct my_error_mgr jerr;
+
+   JSAMPARRAY buffer;// Output row buffer
+  
+   // rappel :
+   // ------
+   // typedef unsigned char JSAMPLE;
+   // typedef JSAMPLE FAR *JSAMPROW;/* ptr to one image row of pixel samples. */
+   // typedef JSAMPROW *JSAMPARRAY;/* ptr to some rows (a 2-D sample array) */
+   // typedef JSAMPARRAY *JSAMPIMAGE;/* a 3-D sample array: top index is color */
+
+   int row_stride;// physical row width in output buffer
+  
+  // We set up the normal JPEG error routines, then override error_exit.
+  
+  cinfo.err = jpeg_std_error(&jerr.pub);
+  // for any jpeg error call my_error_exit
+  jerr.pub.error_exit = my_error_exit;
+  // for any output message call my_output_message
+  //jerr.pub.output_message = my_output_message;
+
+  // Establish the setjmp return context for my_error_exit to use.
+  if (setjmp(jerr.setjmp_buffer))
+  {
+    // If we get here, the JPEG code has signaled an error.
+    // We need to clean up the JPEG object, close the input file, and return.
+
+    gdcmErrorMacro( "Serious Problem !" );
+    jpeg_destroy_decompress(&cinfo);
+    return 0;
+  }
+  // Now we can initialize the JPEG decompression object.
+  if ( statesuspension == 0 )
+    {
+    jpeg_create_decompress(&cinfo);
+    jpeg_stdio_src(&cinfo, fp, this, 1);
+    }
+  else
+    {
+    jpeg_stdio_src(&cinfo, fp, this, 0);
+    }
+   // Step 3: read file parameters with jpeg_read_header()
+
+   if ( statesuspension < 2 )
+   {
+      if ( jpeg_read_header(&cinfo, TRUE) == JPEG_SUSPENDED )
+      {
+      // Suspension in jpeg_read_header
+      statesuspension = 2; 
+      }
+ 
+      // Step 4: set parameters for decompression
+      // prevent the library from performing any color space conversion
+      if ( cinfo.process == JPROC_LOSSLESS )
+      {
+         cinfo.jpeg_color_space = JCS_UNKNOWN;
+         cinfo.out_color_space = JCS_UNKNOWN;
+      }
+   }
+
+   // Step 5: Start decompressor
+   if (statesuspension < 3 )
+   {
+      if ( jpeg_start_decompress(&cinfo) == FALSE )
+      {
+         // Suspension: jpeg_start_decompress
+         statesuspension = 3;
+      }
+
+      // JSAMPLEs per row in output buffer
+      row_stride = cinfo.output_width * cinfo.output_components*2;
+  
+      // Make a one-row-high sample array that will go away when done with image
+      buffer = (*cinfo.mem->alloc_sarray)
+            ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
+
+      // Step 6: while (scan lines remain to be read)
+
+      // Save the buffer in case of suspension to be able to reuse it later:
+      SampBuffer = buffer;
+   }
+   else
+   {
+      // Suspension: re-use the buffer:
+      buffer = (JSAMPARRAY)SampBuffer;
+   }
+   int bufsize = cinfo.output_width * cinfo.output_components;
+   size_t rowsize = bufsize * sizeof(JSAMPLE);
+
+   while (cinfo.output_scanline < cinfo.output_height)
+   {
+      if ( jpeg_read_scanlines(&cinfo, buffer, 1) == 0 )
+        {
+        // Suspension in jpeg_read_scanlines
+        statesuspension = 3;
+        return true;
+        }
+// The ijg has no notion of big endian, therefore always swap the jpeg stream
+#if (defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)) && (CMAKE_BITS_IN_JSAMPLE != 8)
+      uint16_t *buffer16 = (uint16_t*)*buffer;
+      uint16_t *pimage16 = (uint16_t*)pImage;
+      for(unsigned int i=0;i<rowsize/2;i++)
+        pimage16[i] = (buffer16[i] >> 8) | (buffer16[i] << 8 );
+#else
+      memcpy( pImage, *buffer,rowsize);
+#endif //GDCM_WORDS_BIGENDIAN
+      pImage+=rowsize;
+   }
+
+   // Step 7: Finish decompression
+   if ( jpeg_finish_decompress(&cinfo) == FALSE )
+     {
+     // Suspension: jpeg_finish_decompress
+     statesuspension = 4;
+     }
+   
+   // Step 8: Release JPEG decompression object
+   jpeg_destroy_decompress(&cinfo);
+
+   // At this point you may want to check to see whether any corrupt-data
+   // warnings occurred (test whether jerr.pub.num_warnings is nonzero).
+
+   return true;
+}
+
+#ifdef _MSC_VER
+// Put the warning back
+#pragma warning( default : 4611 )
+#endif
+
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg12.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg12.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c9728484a1efd33cc9de42e22e033ca60ca6c42f
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg12.cxx
@@ -0,0 +1,33 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmJpeg12.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.6 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+#include "gdcmFileHelper.h"
+#include <stdio.h>
+
+extern "C" {
+#include "itkjpeg/12/jconfig.h"
+#include "itkjpeg/12/jpeglib.h"
+#include "itkjpeg/12/jinclude.h"
+#include "itkjpeg/12/jerror.h"
+}
+
+#define gdcm_write_JPEG_file  gdcm_write_JPEG_file12
+#define ReadJPEGFile   ReadJPEGFile12
+#define SampBuffer SampBuffer12
+
+#include "gdcmJpeg.cxx"
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg16.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg16.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8a6dccd90ae46affce029c84ae37b9da654ac421
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg16.cxx
@@ -0,0 +1,33 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmJpeg16.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.6 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+#include "gdcmFileHelper.h"
+#include <stdio.h>
+
+extern "C" {
+#include "itkjpeg/16/jconfig.h"
+#include "itkjpeg/16/jpeglib.h"
+#include "itkjpeg/16/jinclude.h"
+#include "itkjpeg/16/jerror.h"
+}
+
+#define gdcm_write_JPEG_file  gdcm_write_JPEG_file16
+#define ReadJPEGFile   ReadJPEGFile16
+#define SampBuffer SampBuffer16
+
+#include "gdcmJpeg.cxx"
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg2000.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg2000.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e77308ef5d719dd93e42055c7bc514a3d444e6c1
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg2000.cxx
@@ -0,0 +1,350 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmJpeg2000.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:46:05 $
+  Version:   $Revision: 1.6 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+#include "gdcmFileHelper.h"
+#include "gdcmDebug.h"
+
+#include <iostream>
+#include <fstream>
+
+#if defined(__BORLANDC__)
+   #include <mem.h> // for memset
+#endif 
+
+extern "C" {
+  #include "openjpeg/openjpeg.h"
+}
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+ /**
+ * \brief   routine for JPEG decompression 
+ * @param raw raw
+ * @param inputdata inputdata
+ * @param inputlength inputlength 
+ * @return 1 on success, 0 on error
+ */
+
+/**
+sample error callback expecting a FILE* client object
+*/
+void error_callback(const char *msg, void *) {
+  std::cerr << "Error in gdcmopenjpeg" << msg << std::endl;
+}
+/**
+sample warning callback expecting a FILE* client object
+*/
+void warning_callback(const char *msg, void *) {
+  std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl;
+}
+/**
+sample debug callback expecting no client object
+*/
+void info_callback(const char *msg, void *) {
+  std::cerr << "Info in gdcmopenjpeg" << msg << std::endl;
+}
+
+#define J2K_CFMT 0
+#define JP2_CFMT 1
+#define JPT_CFMT 2
+#define MJ2_CFMT 3
+#define PXM_DFMT 0
+#define PGX_DFMT 1
+#define BMP_DFMT 2
+#define YUV_DFMT 3
+
+/*
+ * Divide an integer by a power of 2 and round upwards.
+ *
+ * a divided by 2^b
+ */
+inline int int_ceildivpow2(int a, int b) {
+  return (a + (1 << b) - 1) >> b;
+}
+
+/*
+ * The following function was copy paste from j2k_to_image.c with part from convert.c
+ */
+bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
+{
+  opj_dparameters_t parameters;  /* decompression parameters */
+  opj_event_mgr_t event_mgr;    /* event manager */
+  opj_image_t *image;
+  opj_dinfo_t* dinfo;  /* handle to a decompressor */
+  opj_cio_t *cio;
+  unsigned char *src = (unsigned char*)inputdata; 
+  int file_length = inputlength;
+
+  /* configure the event callbacks (not required) */
+  memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+  event_mgr.error_handler = error_callback;
+  event_mgr.warning_handler = warning_callback;
+  event_mgr.info_handler = info_callback;
+
+  /* set decoding parameters to default values */
+  opj_set_default_decoder_parameters(&parameters);
+ 
+   // default blindly copied
+   parameters.cp_layer=0;
+   parameters.cp_reduce=0;
+//   parameters.decod_format=-1;
+//   parameters.cod_format=-1;
+
+      /* JPEG-2000 codestream */
+    parameters.decod_format = J2K_CFMT;
+    assert(parameters.decod_format == J2K_CFMT);
+  parameters.cod_format = PGX_DFMT;
+  assert(parameters.cod_format == PGX_DFMT);
+
+      /* get a decoder handle */
+      dinfo = opj_create_decompress(CODEC_J2K);
+      
+      /* catch events using our callbacks and give a local context */
+      opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);      
+
+      /* setup the decoder decoding parameters using user parameters */
+      opj_setup_decoder(dinfo, &parameters);
+
+      /* open a byte stream */
+      cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
+
+      /* decode the stream and fill the image structure */
+      image = opj_decode(dinfo, cio);
+      if(!image) {
+        opj_destroy_decompress(dinfo);
+        opj_cio_close(cio);
+        return 1;
+      }
+      
+      /* close the byte stream */
+      opj_cio_close(cio);
+
+  /* free the memory containing the code-stream */
+  delete[] src;  //FIXME
+
+   // Copy buffer
+   for (int compno = 0; compno < image->numcomps; compno++)
+   {
+      opj_image_comp_t *comp = &image->comps[compno];
+  
+      int w = image->comps[compno].w;
+      int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor);
+  
+      //int h = image.comps[compno].h;
+      int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor);
+  
+      if (comp->prec <= 8)
+      {
+         uint8_t *data8 = (uint8_t*)raw;
+         for (int i = 0; i < wr * hr; i++) 
+         {
+            int v = image->comps[compno].data[i / wr * w + i % wr];
+            *data8++ = (uint8_t)v;
+         }
+      }
+      else if (comp->prec <= 16)
+      {
+         uint16_t *data16 = (uint16_t*)raw;
+         for (int i = 0; i < wr * hr; i++) 
+         {
+            int v = image->comps[compno].data[i / wr * w + i % wr];
+            *data16++ = (uint16_t)v;
+         }
+      }
+      else
+      {
+         uint32_t *data32 = (uint32_t*)raw;
+         for (int i = 0; i < wr * hr; i++) 
+         {
+            int v = image->comps[compno].data[i / wr * w + i % wr];
+            *data32++ = (uint32_t)v;
+         }
+      }
+      //free(image.comps[compno].data);
+   }
+ 
+
+  /* free remaining structures */
+  if(dinfo) {
+    opj_destroy_decompress(dinfo);
+  }
+
+  /* free image data structure */
+  opj_image_destroy(image);
+
+  return true;
+}
+
+#if 0
+// For openjpeg 0.97
+bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
+{
+   j2k_image_t img;
+   j2k_cp_t cp;
+ 
+   // default blindly copied
+   cp.layer=0;
+   cp.reduce=0;
+   cp.decod_format=-1;
+   cp.cod_format=-1;
+ 
+   cp.cod_format=J2K_CFMT;
+   cp.decod_format = PGX_DFMT;
+   int len = inputlength;
+   unsigned char *src = (unsigned char*)inputdata;
+ 
+   // Decompression
+   if (!j2k_decode(src, len, &img, &cp))
+   {
+      gdcmErrorMacro( "ERROR -> j2k_to_image: failed to decode image!" );
+      return false;
+   }
+ 
+   // Copy buffer
+   for (int compno = 0; compno < img.numcomps; compno++)
+   {
+      j2k_comp_t *comp = &img.comps[compno];
+  
+      int w = img.comps[compno].w;
+      int wr = int_ceildivpow2(img.comps[compno].w, img.comps[compno].factor);
+  
+      //int h = img.comps[compno].h;
+      int hr = int_ceildivpow2(img.comps[compno].h, img.comps[compno].factor);
+  
+      if (comp->prec <= 8)
+      {
+         uint8_t *data8 = (uint8_t*)raw;
+         for (int i = 0; i < wr * hr; i++) 
+         {
+            int v = img.comps[compno].data[i / wr * w + i % wr];
+            *data8++ = (uint8_t)v;
+         }
+      }
+      else if (comp->prec <= 16)
+      {
+         uint16_t *data16 = (uint16_t*)raw;
+         for (int i = 0; i < wr * hr; i++) 
+         {
+            int v = img.comps[compno].data[i / wr * w + i % wr];
+            *data16++ = (uint16_t)v;
+         }
+      }
+      else
+      {
+         uint32_t *data32 = (uint32_t*)raw;
+         for (int i = 0; i < wr * hr; i++) 
+         {
+            int v = img.comps[compno].data[i / wr * w + i % wr];
+            *data32++ = (uint32_t)v;
+         }
+      }
+      free(img.comps[compno].data);
+   }
+ 
+   // Free remaining structures
+   j2k_dec_release();
+   // FIXME
+   delete[] inputdata;
+ 
+   return true;
+}
+#endif
+
+#if 0
+bool gdcm_read_JASPER_file (void* raw, char *inputdata, size_t inputlength)
+{
+#if 0
+  std::cerr << "Inputlenght=" << inputlength << std::endl;
+  std::ofstream out("/tmp/jpeg2000.jpc", std::ios::binary);
+  out.write((char*)inputdata,inputlength);
+  out.close();
+#endif
+  jas_init(); //important...
+  jas_stream_t *jasStream = 
+    jas_stream_memopen((char *)inputdata, inputlength);
+    
+  int fmtid;
+  if ((fmtid = jas_image_getfmt(jasStream)) < 0) 
+    {
+    gdcmErrorMacro("unknown image format");
+    return false;
+    }
+
+  // Decode the image. 
+  jas_image_t *jasImage /* = NULL*/; // Useless assignation
+  if (!(jasImage = jas_image_decode(jasStream, fmtid, 0))) 
+    {
+    gdcmErrorMacro("cannot decode image");
+    return false;
+    }
+
+  // close the stream. 
+  jas_stream_close(jasStream);
+  int numcmpts = jas_image_numcmpts(jasImage);
+  int width = jas_image_cmptwidth(jasImage, 0);
+  int height = jas_image_cmptheight(jasImage, 0);
+  int prec = jas_image_cmptprec(jasImage, 0);
+  int i, j, k;
+
+  // The following should serioulsy be rewritten I cannot believe we need to
+  // do a per pixel decompression, there should be a way to read a full
+  // scanline...
+  if (prec == 8)
+    {
+    uint8_t *data8 = (uint8_t*)raw;
+    for ( i = 0; i < height; i++)
+      for ( j = 0; j < width; j++)
+        for ( k= 0; k < numcmpts; k++)
+          *data8++ = (uint8_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
+    }
+  else if (prec <= 16)
+    {
+    uint16_t *data16 = (uint16_t*)raw;
+    for ( i = 0; i < height; i++) 
+      for ( j = 0; j < width; j++) 
+        for ( k= 0; k < numcmpts; k++)
+          *data16++ = (uint16_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
+    }
+  else if (prec <= 32)
+    {
+    uint32_t *data32 = (uint32_t*)raw;
+    for ( i = 0; i < height; i++) 
+      for ( j = 0; j < width; j++) 
+        for ( k= 0; k < numcmpts; k++)
+          *data32++ = (uint32_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
+    }
+
+  jas_image_destroy(jasImage);
+  jas_image_clearfmts();
+
+  //FIXME
+  //delete the jpeg temp buffer
+#if 0
+  std::ofstream rawout("/tmp/jpeg2000.raw");
+  rawout.write((char*)raw,height*width*numcmpts*((prec+4)/8));
+  rawout.close();
+#endif
+  delete[] inputdata;
+
+  return true;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg8.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg8.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..31a6a51f970644d302460660bcaf811f7592a66d
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmJpeg8.cxx
@@ -0,0 +1,33 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmJpeg8.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.6 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+#include "gdcmFileHelper.h"
+#include <stdio.h>
+
+extern "C" {
+#include "itkjpeg/8/jconfig.h"
+#include "itkjpeg/8/jpeglib.h"
+#include "itkjpeg/8/jinclude.h"
+#include "itkjpeg/8/jerror.h"
+}
+
+#define gdcm_write_JPEG_file  gdcm_write_JPEG_file8
+#define ReadJPEGFile   ReadJPEGFile8
+#define SampBuffer SampBuffer8
+
+#include "gdcmJpeg.cxx"
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmJpegLS.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmJpegLS.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5cf1b0eb5850c09ddb9d8740412fc2e273e5bb60
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmJpegLS.cxx
@@ -0,0 +1,51 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmJpegLS.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+#include "gdcmFileHelper.h"
+#include "gdcmDebug.h"
+
+#include <iostream>
+#include <fstream>
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+ /**
+ * \brief   routine for JPEG decompression. WARNING LPEG-LS is NOT
+ *   the 'classical' jpeg lossless. See :
+ *   http://www.jpeg.org/jpeg/jpegls.html
+ *   gdcm DOES deal with 'classical' jpeg lossless
+ *
+ * @param fp pointer to an already open file descriptor 
+ *                      JPEG-LS encoded image
+ * @param image_buffer to receive uncompressed pixels
+ * @return 1 on success, 0 on error
+ * @warning : not yet made
+ */
+
+bool gdcm_read_JPEGLS_file (std::ifstream *fp, void *image_buffer)
+{
+   (void)fp;
+   (void)image_buffer;
+   gdcmWarningMacro( "Sorry JPEG-LS File not yet taken into account" );
+   return false;
+}
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmMpeg.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmMpeg.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..587037837f70644887def74f8ac2fdec0102e801
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmMpeg.cxx
@@ -0,0 +1,421 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmMpeg.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.2 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+#include "gdcmDebug.h"
+
+#include <fstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <fcntl.h>
+extern "C" {
+#define GLOBAL
+#include "config.h"
+#include "global.h"
+
+/* private prototypes */
+static int  video_sequence        _ANSI_ARGS_((int *framenum));
+static int  Decode_Bitstream      _ANSI_ARGS_((void));
+static int  Headers               _ANSI_ARGS_((void));
+static void Initialize_Sequence   _ANSI_ARGS_((void));
+static void Initialize_Decoder    _ANSI_ARGS_((void));
+static void Deinitialize_Sequence _ANSI_ARGS_((void));
+//static void Process_Options       _ANSI_ARGS_((int argc, char *argv[]));
+
+/* IMPLEMENTATION specific routines */
+static void Initialize_Decoder()
+{
+  int i;
+
+  /* Clip table */
+  if ( !(Clip=(unsigned char *)malloc(1024)) )
+    Error("Clip[] malloc failed\n");
+
+  Clip += 384;
+
+  for (i=-384; i<640; i++)
+    Clip[i] = (i<0) ? 0 : ((i>255) ? 255 : i);
+
+  /* IDCT */
+  if ( Reference_IDCT_Flag )
+    Initialize_Reference_IDCT();
+  else
+    Initialize_Fast_IDCT();
+
+}
+
+/* mostly IMPLEMENTATION specific routines */
+static void Initialize_Sequence()
+{
+  int cc, size;
+  static int Table_6_20[3] = {6,8,12};
+
+  /* check scalability mode of enhancement layer */
+  if ( Two_Streams && (enhan.scalable_mode!=SC_SNR) 
+      &&
+       (base.scalable_mode!=SC_DP) )
+  {
+     Error("unsupported scalability mode\n");
+  }
+  /* force MPEG-1 parameters for proper decoder behavior */
+  /* see ISO/IEC 13818-2 section D.9.14 */
+  if ( !base.MPEG2_Flag )
+  {
+    progressive_sequence = 1;
+    progressive_frame = 1;
+    picture_structure = FRAME_PICTURE;
+    frame_pred_frame_dct = 1;
+    chroma_format = CHROMA420;
+    matrix_coefficients = 5;
+  }
+
+  /* round to nearest multiple of coded macroblocks */
+  /* ISO/IEC 13818-2 section 6.3.3 sequence_header() */
+  mb_width = (horizontal_size+15)/16;
+  mb_height = (base.MPEG2_Flag && !progressive_sequence) ? 2*((vertical_size+31)/32)
+                                        : (vertical_size+15)/16;
+
+  Coded_Picture_Width = 16*mb_width;
+  Coded_Picture_Height = 16*mb_height;
+
+  /* ISO/IEC 13818-2 sections 6.1.1.8, 6.1.1.9, and 6.1.1.10 */
+  Chroma_Width = (chroma_format==CHROMA444) ? Coded_Picture_Width
+                                           : Coded_Picture_Width>>1;
+  Chroma_Height = (chroma_format!=CHROMA420) ? Coded_Picture_Height
+                                            : Coded_Picture_Height>>1;
+  
+  /* derived based on Table 6-20 in ISO/IEC 13818-2 section 6.3.17 */
+  block_count = Table_6_20[chroma_format-1];
+
+  for (cc=0; cc<3; cc++)
+  {
+    if ( cc==0 )
+      size = Coded_Picture_Width*Coded_Picture_Height;
+    else
+      size = Chroma_Width*Chroma_Height;
+
+    if ( !(backward_reference_frame[cc] = (unsigned char *)malloc(size)) )
+      Error("backward_reference_frame[] malloc failed\n");
+
+    if ( !(forward_reference_frame[cc] = (unsigned char *)malloc(size)) )
+      Error("forward_reference_frame[] malloc failed\n");
+
+    if ( !(auxframe[cc] = (unsigned char *)malloc(size)) )
+      Error("auxframe[] malloc failed\n");
+
+    if (  Ersatz_Flag )
+      if ( !(substitute_frame[cc] = (unsigned char *)malloc(size)) )
+        Error("substitute_frame[] malloc failed\n");
+
+
+    if ( base.scalable_mode==SC_SPAT )
+    {
+      /* this assumes lower layer is 4:2:0 */
+      if ( !(llframe0[cc] = (unsigned char *)malloc((lower_layer_prediction_horizontal_size*lower_layer_prediction_vertical_size)/(cc?4:1))))
+        Error("llframe0 malloc failed\n");
+      if ( !(llframe1[cc] = (unsigned char *)malloc((lower_layer_prediction_horizontal_size*lower_layer_prediction_vertical_size)/(cc?4:1))))
+        Error("llframe1 malloc failed\n");
+    }
+  }
+
+  /* SCALABILITY: Spatial */
+  if ( base.scalable_mode==SC_SPAT )
+  {
+    if ( !(lltmp = (short *)malloc(lower_layer_prediction_horizontal_size*((lower_layer_prediction_vertical_size*vertical_subsampling_factor_n)/vertical_subsampling_factor_m)*sizeof(short))))
+      Error("lltmp malloc failed\n");
+  }
+
+#ifdef DISPLAY
+  if (Output_Type==T_X11)
+  {
+    Initialize_Display_Process("");
+    Initialize_Dither_Matrix();
+  }
+#endif /* DISPLAY */
+
+}
+
+extern void Error(char *text)
+{
+  fprintf(stderr,text);
+  exit(1);
+}
+
+/* Trace_Flag output */
+void Print_Bits(int code, int bits, int len)
+{
+  int i;
+  for (i=0; i<len; i++)
+    printf("%d",(code>>(bits-1-i))&1);
+}
+
+static int Headers()
+{
+  int ret;
+
+  ld = &base;
+  
+  /* return when end of sequence (0) or picture
+     header has been parsed (1) */
+
+  ret = Get_Hdr();
+
+
+  if (Two_Streams)
+  {
+    ld = &enhan;
+    if (Get_Hdr()!=ret && !Quiet_Flag)
+      fprintf(stderr,"streams out of sync\n");
+    ld = &base;
+  }
+
+  return ret;
+}
+
+
+
+static int Decode_Bitstream()
+{
+  int ret;
+  int Bitstream_Framenum;
+
+  Bitstream_Framenum = 0;
+
+  for(;;)
+  {
+
+#ifdef VERIFY
+    Clear_Verify_Headers();
+#endif /* VERIFY */
+
+    ret = Headers();
+    
+    if ( ret==1 )
+    {
+      ret = video_sequence(&Bitstream_Framenum);
+    }
+    else
+      return(ret);
+  }
+
+}
+
+
+static void Deinitialize_Sequence()
+{
+  int i;
+
+  /* clear flags */
+  base.MPEG2_Flag=0;
+
+  for(i=0;i<3;i++)
+  {
+    free(backward_reference_frame[i]);
+    free(forward_reference_frame[i]);
+    free(auxframe[i]);
+
+    if ( base.scalable_mode==SC_SPAT )
+    {
+     free(llframe0[i]);
+     free(llframe1[i]);
+    }
+  }
+
+  if ( base.scalable_mode==SC_SPAT )
+    free(lltmp);
+
+#ifdef DISPLAY
+  if ( Output_Type==T_X11 ) 
+    Terminate_Display_Process();
+#endif
+}
+
+
+static int video_sequence(int *Bitstream_Framenumber)
+{
+  int Bitstream_Framenum;
+  int Sequence_Framenum;
+  int Return_Value;
+
+  Bitstream_Framenum = *Bitstream_Framenumber;
+  Sequence_Framenum=0;
+
+  Initialize_Sequence();
+
+  /* decode picture whose header has already been parsed in 
+     Decode_Bitstream() */
+
+
+  Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
+
+  /* update picture numbers */
+  if ( !Second_Field )
+  {
+    Bitstream_Framenum++;
+    Sequence_Framenum++;
+  }
+
+  /* loop through the rest of the pictures in the sequence */
+  while ((Return_Value=Headers()))
+  {
+    Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
+
+    if ( !Second_Field )
+    {
+      Bitstream_Framenum++;
+      Sequence_Framenum++;
+    }
+  }
+
+  /* put last frame */
+  if (Sequence_Framenum!=0)
+  {
+    Output_Last_Frame_of_Sequence(Bitstream_Framenum);
+  }
+
+  Deinitialize_Sequence();
+
+#ifdef VERIFY
+    Clear_Verify_Headers();
+#endif /* VERIFY */
+
+  *Bitstream_Framenumber = Bitstream_Framenum;
+  return(Return_Value);
+}
+} // End "C" extern
+
+namespace gdcm 
+{
+/**
+ * \brief   routine for MPEG decompression 
+ * @param fp pointer to an already open file descriptor 
+ *                      8 significant bits per pixel
+ * @param image_buffer to receive uncompressed pixels
+ * @param length length
+ * @return 1 on success, 0 on error
+ */
+
+bool ReadMPEGFile (std::ifstream *fp, void *image_buffer, size_t length)
+{
+  int ret, code;
+
+#if 0
+  fp->read((char*)image_buffer, length);
+
+  ofstream out("/tmp/etiam.mpeg");
+  out.write((char*)image_buffer, length);
+  out.close();
+#endif
+
+//  Clear_Options();
+
+  /* decode command line arguments */
+//  Process_Options(argc,argv);
+
+#ifdef DEBUG
+  Print_Options();
+#endif
+
+  ld = &base; /* select base layer context */
+
+  /* open MPEG base layer bitstream file(s) */
+  /* NOTE: this is either a base layer stream or a spatial enhancement stream */
+#if 0
+  if ((base.Infile=open(Main_Bitstream_Filename,O_RDONLY|O_BINARY))<0)
+  {
+    fprintf(stderr,"Base layer input file %s not found\n", Main_Bitstream_Filename);
+    exit(1);
+  }
+#else
+  base.Infile = -1; //DEBUG
+#endif
+
+
+  if ( base.Infile != 0 )
+  {
+    Initialize_Buffer(); 
+  
+    if ( Show_Bits(8)==0x47 )
+    {
+      sprintf(Error_Text,"Decoder currently does not parse transport streams\n");
+      Error(Error_Text);
+    }
+
+    next_start_code();
+    code = Show_Bits(32);
+
+    switch(code)
+    {
+    case SEQUENCE_HEADER_CODE:
+      break;
+    case PACK_START_CODE:
+      System_Stream_Flag = 1;
+    case VIDEO_ELEMENTARY_STREAM:
+      System_Stream_Flag = 1;
+      break;
+    default:
+      sprintf(Error_Text,"Unable to recognize stream type\n");
+      Error(Error_Text);
+      break;
+    }
+
+    //lseek(base.Infile, 0l, SEEK_SET);
+    //fp->seekg(mpeg_start, ios_base::beg);
+    Initialize_Buffer(); 
+  }
+
+  if ( base.Infile!=0 )
+  {
+    //lseek(base.Infile, 0l, SEEK_SET);
+    //fp->seekg(mpeg_start, ios_base::beg);
+  }
+
+  Initialize_Buffer(); 
+
+  if ( Two_Streams )
+  {
+  abort();
+    ld = &enhan; /* select enhancement layer context */
+
+    if ( (enhan.Infile = open(Enhancement_Layer_Bitstream_Filename,O_RDONLY|O_BINARY))<0)
+    {
+      sprintf(Error_Text,"enhancment layer bitstream file %s not found\n",
+        Enhancement_Layer_Bitstream_Filename);
+
+      Error(Error_Text);
+    }
+
+    Initialize_Buffer();
+    ld = &base;
+  }
+
+  Initialize_Decoder();
+
+  ret = Decode_Bitstream();
+
+  //close(base.Infile);
+
+  if ( Two_Streams )
+    {
+    abort();
+    close(enhan.Infile);
+    }
+
+  return ret;
+}
+
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmOrientation.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmOrientation.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..da703f192cdeccb2af486d8270542aa667493ef7
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmOrientation.cxx
@@ -0,0 +1,698 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmOrientation.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmOrientation.h"
+#include "gdcmFile.h"
+#include "gdcmDebug.h"
+#include <math.h> // for sqrt
+
+namespace gdcm 
+{
+//--------------------------------------------------------------------
+//  THERALYS Algorithm to determine the most similar basic orientation
+//
+//  Transliterated from original Python code.
+//  Kept as close as possible to the original code
+//  in order to speed up any further modif of Python code :-(
+//-----------------------------------------------------------------------
+
+/**
+ * \brief  THERALYS' Algorithm to determine the most similar basic orientation
+ *           (Axial, Coronal, Sagital) of the image
+ * \note Should be run on the first gdcm::File of a 'coherent' Serie
+ * @return orientation code
+ *   #   0 : Not Applicable (neither 0020,0037 Image Orientation Patient 
+ *   #                       nor     0020,0032 Image Position           found)
+ *   #   1 : Axial
+ *   #  -1 : Axial invert
+ *   #   2 : Coronal
+ *   #  -2 : Coronal invert
+ *   #   3 : Sagital
+ *   #  -3 : Sagital invert
+ *   #   4 : Heart Axial
+ *   #  -4 : Heart Axial invert
+ *   #   5 : Heart Coronal
+ *   #  -5 : Heart Coronal invert
+ *   #   6 : Heart Sagital
+ *   #  -6 : Heart Sagital invert
+ */
+
+static const char  *OrientationTypeStrings[] = { 
+  "Not Applicable",
+  "Axial",
+  "Coronal",
+  "Sagital",
+  "Heart Axial",
+  "Heart Coronal",
+  "Heart Sagital",
+  "Axial invert",
+  "Coronal invert",
+  "Sagital invert",
+  "Heart Axial invert",
+  "Heart Coronal invert",
+  "Heart Sagital invert",
+  NULL
+};
+
+/// \brief returns human readable interpretation of the most 
+///        similar basic orientation (Axial, Coronal, Sagital, ...) of the image
+const char* Orientation::GetOrientationTypeString(OrientationType const o)
+{
+  int k = (int)o;
+  if (k < 0) 
+       k = -k + 6;
+
+  return OrientationTypeStrings[k];
+}
+
+/// \brief returns of the most similar basic orientation
+///        (Axial, Coronal, Sagital, ...) of the image
+OrientationType Orientation::GetOrientationType( File *f )
+{
+   float iop[6];
+   bool succ = f->GetImageOrientationPatient( iop );
+   if ( !succ )
+   {
+      gdcmErrorMacro( "No Image Orientation (0020,0037)/(0020,0032) found in the file, cannot proceed." )
+      return NotApplicable;
+   }
+   vector3D ori1;
+   vector3D ori2;
+
+   ori1.x = iop[0]; ori1.y = iop[1]; ori1.z = iop[2]; 
+   ori2.x = iop[3]; ori2.y = iop[4]; ori2.z = iop[5];
+
+   // two perpendicular vectors describe one plane
+   double dicPlane[6][2][3] =
+   { {  { 1,   0,    0   },{ 0,      1,     0     }  }, // Axial
+     {  { 1,   0,    0   },{ 0,      0,    -1     }  }, // Coronal
+     {  { 0,   1,    0   },{ 0,      0,    -1     }  }, // Sagittal
+     {  { 0.8, 0.5,  0.0 },{-0.1,    0.1 , -0.95  }  }, // Axial - HEART
+     {  { 0.8, 0.5,  0.0 },{-0.6674, 0.687, 0.1794}  }, // Coronal - HEART
+     {  {-0.1, 0.1, -0.95},{-0.6674, 0.687, 0.1794}  }  // Sagittal - HEART
+   };
+
+   vector3D refA;
+   vector3D refB;
+   int i = 0;
+   Res res;   // [ <result> , <memory of the last succes calcule> ]
+   res.first = 0;
+   res.second = 99999;
+
+   for (int numDicPlane=0; numDicPlane<6; numDicPlane++)
+   {
+       ++i;
+       // refA=plane[0]
+       refA.x = dicPlane[numDicPlane][0][0]; 
+       refA.y = dicPlane[numDicPlane][0][1]; 
+       refA.z = dicPlane[numDicPlane][0][2];
+       // refB=plane[1]
+       refB.x = dicPlane[numDicPlane][1][0]; 
+       refB.y = dicPlane[numDicPlane][1][1]; 
+       refB.z = dicPlane[numDicPlane][1][2];
+       res=VerfCriterion(  i, CalculLikelyhood2Vec(refA,refB,ori1,ori2), res );
+       res=VerfCriterion( -i, CalculLikelyhood2Vec(refB,refA,ori1,ori2), res );
+   }
+   // res thought looks like is a float value, but is indeed an int
+   // try casting it to int first then enum value to please VS7:
+   int int_res = (int)res.first;
+   gdcmAssertMacro( int_res <= 6 && int_res >= -6);
+   return (OrientationType)int_res;
+}
+
+Res 
+Orientation::VerfCriterion(int typeCriterion, double criterionNew, Res const &in)
+{
+   Res res;
+   double type = in.first;
+   double criterion = in.second;
+   if (/*criterionNew < 0.1 && */criterionNew < criterion)
+   {
+      type      = typeCriterion;
+      criterion = criterionNew;
+   }
+   res.first  = type;
+   res.second = criterion;
+   return res;
+} 
+
+inline double square_dist(vector3D const &v1, vector3D const &v2)
+{
+  double res;
+  res = (v1.x - v2.x)*(v1.x - v2.x) +
+        (v1.y - v2.y)*(v1.y - v2.y) +
+        (v1.z - v2.z)*(v1.z - v2.z);
+  return res;
+}
+
+//------------------------- Purpose : -----------------------------------
+//- This function determines the orientation similarity of two planes.
+//  Each plane is described by two vectors.
+//------------------------- Parameters : --------------------------------
+//- <refA>  : - type : vector 3D (double)
+//- <refB>  : - type : vector 3D (double)
+//            - Description of the first plane
+//- <ori1>  : - type : vector 3D (double)
+//- <ori2>  : - type : vector 3D (double)
+//            - Description of the second plane
+//------------------------- Return : ------------------------------------
+// double :   0 if the planes are perpendicular. While the difference of
+//            the orientation between the planes are big more enlarge is
+//            the criterion.
+//------------------------- Other : -------------------------------------
+// The calculus is based with vectors normalice
+double
+Orientation::CalculLikelyhood2Vec(vector3D const &refA, vector3D const &refB, 
+                                  vector3D const &ori1, vector3D const &ori2 )
+{
+
+   vector3D ori3 = ProductVectorial(ori1,ori2);
+   vector3D refC = ProductVectorial(refA,refB);
+   double res = square_dist(refC, ori3);
+
+   return sqrt(res);
+}
+
+//------------------------- Purpose : -----------------------------------
+//- Calculus of the poduct vectorial between two vectors 3D
+//------------------------- Parameters : --------------------------------
+//- <vec1>  : - type : vector 3D (double)
+//- <vec2>  : - type : vector 3D (double)
+//------------------------- Return : ------------------------------------
+// (vec) :    - Vector 3D
+//------------------------- Other : -------------------------------------
+vector3D
+Orientation::ProductVectorial(vector3D const &vec1, vector3D const &vec2)
+{
+   vector3D vec3;
+   vec3.x =    vec1.y*vec2.z - vec1.z*vec2.y;
+   vec3.y = -( vec1.x*vec2.z - vec1.z*vec2.x);
+   vec3.z =    vec1.x*vec2.y - vec1.y*vec2.x;
+
+   return vec3;
+}
+
+
+
+// ---------------------------------------------------------------------------
+// Here is the original Python code, kindly supplied by THERALYS
+//
+// C++ code doesn't give good results
+// --> FIXME
+
+/*
+
+def TypeOrientation(self,file0):
+"""
+# ------------------------- Purpose : -----------------------------------
+# - This function compare the orientation of the given image and the
+#   basics orientations (Axial, Cornal, Sagital)
+# ------------------------- Parameters : --------------------------------
+# - <file0> : - type : string
+#             - The name of the first image file of the serie
+# ------------------------- Return : ------------------------------------
+#   1 :   Axial
+#  -1 :   Axial invert
+#   2 :   Coronal
+#  -2 :   Coronal invert
+#   3 :   Sagital
+#  -3 :   Sagital invert
+#   4 :   Heart Axial
+#  -4 :   Heart Axial invert
+#   5 :   Heart Coronal
+#  -5 :   Heart Coronal invert
+#   6 :   Heart Sagital
+#  -6 :   Heart Sagital invert
+#
+   # ------------------------- Other : -------------------------------------
+# This method finds the most similar basic orientation.
+"""
+try:
+   toRead = gdcm.File(file0)
+   ValDict = GetValuesDict(toRead)
+   try:
+      imageOrientation=ValDict["Image Orientation (Patient)"]
+   except KeyError:
+      imageOrientation=ValDict["Image Orientation"]
+
+   ori1=[float(split(imageOrientation,"\\")[0]),\
+      float(split(imageOrientation,"\\")[1]),\
+      float(split(imageOrientation,"\\")[2])]
+   ori2=[float(split(imageOrientation,"\\")[3]),\
+      float(split(imageOrientation,"\\")[4]),\
+      float(split(imageOrientation,"\\")[5])]
+
+## two vectors perpendicular describe one plane
+   dicPlane=[ [  [1,0,0],[0,1,0]   ],  ## Axial
+            [  [1,0,0],[0,0,-1]  ],  ## Coronal
+            [  [0,1,0],[0,0,-1]  ],  ## Sagittal
+            [  [ 0.8 , 0.5 ,  0.0 ],[-0.1 , 0.1 , -0.95]        ],## Axial - HEART
+            [  [ 0.8 , 0.5 ,  0.0 ],[-0.6674 , 0.687 , 0.1794]  ],## Coronal - HEART
+            [  [-0.1 , 0.1 , -0.95],[-0.6674 , 0.687 , 0.1794]  ] ] ## Sagittal - HEART
+
+   i=0
+   res=[0,99999]  ## [ <result> , <memory of the last succes calcule> ]
+   for plane in dicPlane:
+      i=i+1
+      refA=plane[0]
+      refB=plane[1]
+      res=self.VerfCriterion(  i , self.CalculLikelyhood2Vec(refA,refB,ori1,ori2) , res )
+      res=self.VerfCriterion( -i , self.CalculLikelyhood2Vec(refB,refA,ori1,ori2) , res )
+   return res[0]
+
+   except KeyError:
+   return 0
+
+
+   def VerfCriterion(self,typeCriterion,criterionNew,res):
+      type = res[0]
+      criterion = res[1]
+#     if criterionNew<0.1 and criterionNew<criterion:
+      if criterionNew<criterion:
+         criterion=criterionNew
+         type=typeCriterion
+      return [ type , criterion ]
+
+
+   def CalculLikelyhood2Vec(self,refA,refB,ori1,ori2):
+"""
+   # ------------------------- Purpose : -----------------------------------
+   # - This function determine the orientation similarity of two planes.
+   #   Each plane is described by two vector.
+   # ------------------------- Parameters : --------------------------------
+   # - <refA>  : - type : vector 3D (float)
+   # - <refB>  : - type : vector 3D (float)
+   #             - Description of the first plane
+   # - <ori1>  : - type : vector 3D (float)
+   # - <ori2>  : - type : vector 3D (float)
+   #             - Description of the second plane
+   # ------------------------- Return : ------------------------------------
+   #  float :   0 if the planes are perpendicular. 
+   # While the difference of the orientation between the planes 
+   # are big more enlarge is
+   # the criterion.
+   # ------------------------- Other : -------------------------------------
+   #  The calculus is based with vectors normalice
+   """
+
+      ori3=self.ProductVectorial(ori1,ori2)
+      refC=self.ProductVectorial(refA,refB)
+      res=math.pow(refC[0]-ori3[0],2) + math.pow(refC[1]-ori3[1],2) + math.pow(refC[2]-ori3[2],2)
+      return math.sqrt(res)
+
+   def ProductVectorial(self,vec1,vec2):
+      """
+      # ------------------------- Purpose : -----------------------------------
+      # - Calculus of the poduct vectorial between two vectors 3D
+      # ------------------------- Parameters : --------------------------------
+      # - <vec1>  : - type : vector 3D (float)
+      # - <vec2>  : - type : vector 3D (float)
+      # ------------------------- Return : ------------------------------------
+      #  (vec) :    - Vector 3D
+      # ------------------------- Other : -------------------------------------
+      """
+      vec3=[0,0,0]
+      vec3[0]=vec1[1]*vec2[2] - vec1[2]*vec2[1]
+      vec3[1]=-( vec1[0]*vec2[2] - vec1[2]*vec2[0])
+      vec3[2]=vec1[0]*vec2[1] - vec1[1]*vec2[0]
+      return vec3
+
+   def GetValuesDict(image):
+      """
+      Returns a dictionnary containing values associated with Field Names
+      dict["Dicom Field Name"]="Dicom field value"
+      """
+      val=image.GetFirstEntry()
+      dic={}
+      while(val):
+         if isinstance(val,gdcm.ValEntryPtr):
+            dic[val.GetName()]=val.GetValue()
+         val=image.GetNextEntry()
+      return dic
+
+*/
+
+
+// ------------------------------------------------------------------------
+/*
+2.2.2 Orientation of DICOM images
+
+
+http://www.dclunie.com/medical-image-faq/html/part2.html#DICOMOrientation
+says :
+
+A question that is frequently asked in comp.protocols.dicom is how to determine
+ which side of an image is which (e.g. left, right) and so on. 
+ The short answer is that for projection radiographs this is specified
+ explicitly using the "Patient Orientation" attribute, and for cross-sectional
+ images it needs to be derived from the "Image Orientation (Patient)" direction
+ cosines. In the standard these are explained as follows:
+
+    * "C.7.6.1.1.1 Patient Orientation. 
+                The Patient Orientation (0020,0020) relative to the image
+                plane shall be specified by two values that designate the 
+                anatomical direction of the positive row axis (left to right)
+                and the positive column axis (top to bottom). 
+                The first entry is the direction of the rows, given by the 
+                direction of the last pixel in the first row from the first 
+                pixel in that row. 
+                The second entry is the direction of the columns, given by 
+                the direction of the last pixel in the first column from the
+                first pixel in that column. 
+                Anatomical direction shall be designated by the capital 
+                letters: A (anterior), P (posterior), R (right),L (left), 
+                H (head), F (foot). 
+                Each value of the orientation attribute shall contain at 
+                least one of these characters. 
+                If refinements in the orientation descriptions are to be 
+                specified, then they shall be designated by one or two 
+                additional letters in each value. 
+                Within each value, the letters shall be ordered with the 
+                principal orientation designated in the first character."
+ 
+    * "C.7.6.2.1.1 Image Position And Image Orientation. 
+                The "Image Position (Patient)" (0020,0032) specifies the x, y, 
+                and z coordinates of the upper left hand corner of the image; 
+                it is the center of the first voxel transmitted. 
+                The "Image Orientation (Patient)" (0020,0037) specifies the 
+                direction cosines of the first row and the first column 
+                with respect to the patient. 
+                These Attributes shall be provided as a pair. 
+                Row value for the x, y, and z axes respectively followed by 
+                the Column value for the x, y, and z axes respectively. 
+                The direction of the axes is defined fully by the patient's 
+                orientation. 
+                The x-axis is increasing to the left hand side of the patient.
+                The y-axis is increasing to the posterior side of the patient.
+                The z-axis is increasing toward the head of the patient. 
+                The patient based coordinate system is a right handed system,
+                i.e. the vector cross product of a unit vector along the 
+                positive x-axis and a unit vector along the positive y-axis
+                is equal to a unit vector along the positive z-axis." 
+
+Some simple code to take one of the direction cosines (vectors) from the 
+Image Orientation (Patient) attribute and generate strings equivalent to one 
+of the values of Patient Orientation looks like this (noting that if the vector
+is not aligned exactly with one of the major axes, the resulting string will 
+have multiple letters in as described under "refinements" in C.7.6.1.1.1): 
+
+*/
+
+/**
+ * \brief Computes the Patient Orientation relative to the image plane
+ *          from the 'Image Orientation (Patient)'
+ *          - or from 0020 0035Image Orientation (RET) -
+ *          - The first entry is the direction of the rows, given by the 
+ *          direction of the last pixel in the first row from the first 
+ *          pixel in that row. 
+ *          - The second entry is the direction of the columns, given by 
+ *          the direction of the last pixel in the first column from the
+ *          first pixel in that column. 
+ *          Anatomical direction is designated by the capital 
+ *          letters: A (anterior), P (posterior), R (right),L (left), 
+ *          H (head), F (foot).
+ *          - Refinements in the orientation descriptions are designated 
+ *          by one or two additional letters in each value.
+ *          Use it when "Patient Orientation" (0020,0020) is not found 
+ * @return orientation string as "rowsOrientation\columnsOrientation"
+ */
+std::string Orientation::GetOrientation ( File *f )
+{
+   float iop[6];
+   if ( !f->GetImageOrientationPatient( iop ) )
+   return GDCM_UNFOUND;
+
+   std::string orientation;
+   orientation = GetSingleOrientation ( iop ) 
+               + "\\" 
+               + GetSingleOrientation ( iop + 3 );
+   return orientation;
+}
+
+
+std::string Orientation::GetSingleOrientation ( float *iop)
+{
+   std::string orientation;
+
+   char orientationX = iop[0] < 0 ? 'R' : 'L';
+   char orientationY = iop[1] < 0 ? 'A' : 'P';
+   char orientationZ = iop[2] < 0 ? 'F' : 'H';
+
+   double absX = iop[0];
+   if (absX < 0) absX = -absX;
+      double absY = iop[1];
+   if (absY < 0) absY = -absY;
+      double absZ = iop[2];
+   if (absZ < 0) absZ = -absZ;
+
+   for (int i=0; i<3; ++i) 
+   {
+      if (absX>.0001 && absX>absY && absX>absZ) 
+      {
+         orientation = orientation + orientationX;
+         absX=0;
+       }
+       else if (absY>.0001 && absY>absX && absY>absZ) 
+       {
+          orientation = orientation + orientationY;
+          absY=0;
+       }
+       else if (absZ>.0001 && absZ>absX && absZ>absY) 
+       {
+           orientation = orientation + orientationZ;
+           absZ=0;
+       }
+       else 
+          break;
+     }
+   return orientation;
+} 
+
+
+/*-------------------------------------------------------------------
+
+Some more stuff, from XMedcon
+
+---> Personal remark from JPRx :
+--> patient_position (0x0018,0x5100) can be "HFS ", "FFS ", "HFP ", "FFP " 
+--> or, not so common, 
+// HFDR = Head First-Decubitus Right
+// HFDL = Head First-Decubitus Left
+// FFDR = Feet First-Decubitus Right
+// FFDL = Feet First-Decubitus Left
+--> the cosines may have any value -1.< <+1., for MR images !
+
+enum patient_slice_orientation_type
+  {
+    patient_slice_orientation_unknown = 0,
+    supine_headfirst_transaxial,
+    supine_headfirst_sagittal,
+    supine_headfirst_coronal,
+    supine_feetfirst_transaxial,
+    supine_feetfirst_sagittal,
+    supine_feetfirst_coronal,
+    prone_headfirst_transaxial,
+    prone_headfirst_sagittal,
+    prone_headfirst_coronal,
+    prone_feetfirst_transaxial,
+    prone_feetfirst_sagittal,
+    prone_feetfirst_coronal
+  };
+
+void GetImageOrientationPatient(gdcm::File &h,F32 image_orientation_patient[6])
+{
+  h.GetImageOrientationPatient(image_orientation_patient);
+}
+
+#if 0
+//
+// this is all completely cribbed from the xmedcon library, since
+// we're trying to do what it does, mostly.
+patient_slice_orientation_type
+GetPatSliceOrient(gdcm::File &h)
+{
+  F32 image_orientation_patient[6];
+
+  // protected, do it the hard way
+  //  h.GetImageOrientationPatient(image_orientation_patient);
+  GetImageOrientationPatient(h,image_orientation_patient);
+
+  enum { headfirst, feetfirst } patient_orientation;
+  enum { supine, prone } patient_rotation;
+  enum { transaxial, sagittal, coronal } slice_orientation;
+
+  std::string patient_position = h.GetEntryByNumber(0x0018,0x5100);
+  if(patient_position == "gdcm::Unfound")
+    {
+    patient_position = "HF";
+    }
+  if(patient_position.find("HF") != std::string::npos)
+    {
+    patient_orientation = headfirst;
+    }
+  else if(patient_position.find("FF") != std::string::npos)
+    {
+    patient_orientation = feetfirst;
+    }
+
+  if(patient_position.find("S") != std::string::npos)
+    {
+    patient_rotation = supine;
+    }
+  else if(patient_position.find("P") != std::string::npos)
+    {
+    patient_rotation = prone;
+    }
+
+  if((image_orientation_patient[0] == 1 || image_orientation_patient[0] == -1) &&
+     (image_orientation_patient[4] == +1 || image_orientation_patient[4] == -1))
+    {
+    slice_orientation = transaxial;
+    }
+  else if((image_orientation_patient[1] == 1 || image_orientation_patient[1] == -1) &&
+          (image_orientation_patient[5] == +1 || image_orientation_patient[5] == -1))
+    {
+    slice_orientation = sagittal;
+    }
+  else if((image_orientation_patient[0] == 1 || image_orientation_patient[0] == -1) &&
+          (image_orientation_patient[5] == +1 || image_orientation_patient[5] == -1))
+    {
+    slice_orientation = coronal;
+    }
+  //
+  // combine results
+  patient_slice_orientation_type patient_slice_orientation = 
+    patient_slice_orientation_unknown;
+  switch (patient_rotation) 
+    {
+    case supine:
+      switch (patient_orientation) 
+        {
+        case headfirst:
+          switch (slice_orientation) 
+            {
+            case transaxial:
+              patient_slice_orientation = supine_headfirst_transaxial;
+              break;
+            case sagittal:
+              patient_slice_orientation = supine_headfirst_sagittal;
+              break;
+            case coronal:
+              patient_slice_orientation = supine_headfirst_coronal;
+              break;
+            }
+          break;
+        case feetfirst:
+          switch (slice_orientation) 
+            {
+            case transaxial:
+              patient_slice_orientation = supine_feetfirst_transaxial;
+              break;
+            case sagittal:
+              patient_slice_orientation = supine_feetfirst_sagittal;
+              break;
+            case coronal:
+              patient_slice_orientation = supine_feetfirst_coronal;
+              break;
+            }
+          break;
+        }
+      break;
+    case prone:
+      switch (patient_orientation) 
+        {
+        case headfirst:
+          switch (slice_orientation) 
+            {
+            case transaxial:
+              patient_slice_orientation = prone_headfirst_transaxial;
+              break;
+            case sagittal:
+              patient_slice_orientation = prone_headfirst_sagittal;
+              break;
+            case coronal:
+              patient_slice_orientation = prone_headfirst_coronal;
+              break;
+            }
+          break;
+        case feetfirst:
+          switch (slice_orientation) 
+            {
+            case transaxial:
+              patient_slice_orientation = prone_feetfirst_transaxial;
+              break;
+            case sagittal:
+              patient_slice_orientation = prone_feetfirst_sagittal;
+              break;
+            case coronal:
+              patient_slice_orientation = prone_feetfirst_coronal;
+              break;
+            }
+          break;
+        }
+      break;
+    }
+  if(patient_slice_orientation != patient_slice_orientation_unknown)
+    return patient_slice_orientation;
+  //
+  // this is what xmedcon does
+  if ((image_orientation_patient[0] == +1)   &&
+      (image_orientation_patient[4] == +1))   
+    patient_slice_orientation = supine_headfirst_transaxial;
+  else if ((image_orientation_patient[0] == -1)   &&
+           (image_orientation_patient[4] == +1))   
+    patient_slice_orientation = supine_feetfirst_transaxial;
+  else if ((image_orientation_patient[0] == -1)   &&
+           (image_orientation_patient[4] == -1))   
+    patient_slice_orientation = prone_headfirst_transaxial;
+  else if ((image_orientation_patient[0] == +1)   &&
+           (image_orientation_patient[4] == -1))   
+    patient_slice_orientation = prone_feetfirst_transaxial;
+
+  else if ((image_orientation_patient[1] == +1)   &&
+           (image_orientation_patient[5] == -1))   
+    patient_slice_orientation = supine_headfirst_sagittal;
+  else if ((image_orientation_patient[1] == +1)   &&
+           (image_orientation_patient[5] == +1))   
+    patient_slice_orientation = supine_feetfirst_sagittal;
+  else if ((image_orientation_patient[1] == -1)   &&
+           (image_orientation_patient[5] == -1))   
+    patient_slice_orientation = prone_headfirst_sagittal;
+  else if ((image_orientation_patient[1] == -1)   &&
+           (image_orientation_patient[5] == +1))   
+    patient_slice_orientation = prone_feetfirst_sagittal;
+
+  else if ((image_orientation_patient[0] == +1)   &&
+           (image_orientation_patient[5] == -1))   
+    patient_slice_orientation = supine_headfirst_coronal;
+  else if ((image_orientation_patient[0] == -1)   &&
+           (image_orientation_patient[5] == +1))   
+    patient_slice_orientation = supine_feetfirst_coronal;
+  else if ((image_orientation_patient[0] == -1)   &&
+           (image_orientation_patient[5] == -1))   
+    patient_slice_orientation = prone_headfirst_coronal;
+  else if ((image_orientation_patient[0] == +1)   &&
+           (image_orientation_patient[5] == +1))   
+    patient_slice_orientation = prone_feetfirst_coronal;
+  return patient_slice_orientation;
+}
+#else
+
+-------------------------------------------------------------------------*/
+
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmOrientation.h b/Utilities/ITK/Utilities/gdcm/src/gdcmOrientation.h
new file mode 100644
index 0000000000000000000000000000000000000000..0002acc70237dca3a993197318fcb76aae75029e
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmOrientation.h
@@ -0,0 +1,118 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmOrientation.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMORIENTATION_H
+#define GDCMORIENTATION_H
+
+#include "gdcmBase.h"
+#include <map>
+
+namespace gdcm 
+{
+typedef struct
+{
+   double x;
+   double y;
+   double z;
+} vector3D;
+
+typedef std::pair<double, double> Res;
+class File;
+
+typedef enum {
+   NotApplicable = 0,
+   Axial = 1,
+   AxialInvert = -1,
+   Coronal = 2,
+   CoronalInvert = -2,
+   Sagital = 3,
+   SagitalInvert = -3,
+   HeartAxial = 4,
+   HeartAxialInvert = -4,
+   HeartCoronal = 5,
+   HeartCoronalInvert = -5,
+   HeartSagital = 6,
+   HeartSagitalInvert = -6
+} OrientationType;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief Orientation class for dealing with DICOM image orientation
+ *
+ * A gentle reminder for non-medical user:
+ * PatientPosition (0x0010,0x5100) tells us the way the patient was introduced in the imager
+ *  - HFS : Head First Supine
+ *  - FFS : Feet First Supine
+ *  - HFP : Head First Prone
+ *  - FFP : Feet First Prone
+ * Note: HFP and FFP are not very common values, since the position must
+ *        be pretty unconfortable for the Patient -the patient is lying on his belly; but, if he has handcuffs there is no other way ...-
+ *
+ * ImageOrientationPatient (0x0020,0x0037) gives 6 cosines (2 for each plane)
+ * Patient Orientation (as found in the optional 0x0020,0x0020, or computed by
+ * std::string Orientation::GetOrientation ( File *f ), tells us about the direction of X and Y axes.
+ * 
+ * The values can be
+ *  - A/P anterior/posterior
+ *  - L/R left/right
+ *  - H/F head/feet
+ * One can see it as "values within a 'Patient referential".
+ *
+ * Example #1:
+ * Imagine the patient, in "HFS" position.
+ * Full body sagital images are requested.
+ * All the cosines will be -1, 0, or +1;
+ * "Patient Orientation" (deduced) will be "A/F".
+ * Positive X axis is oriented 'towards patient's nose
+ * Positive Y axis  is oriented 'towards patient's feet
+ *
+ * Example #2:
+ * Imagine now that patient has a stiffneck and his head is *turned* 30 degrees towards the left.
+ * Head sagital images are requested.
+ * One of the cosines will be almost 0.5
+ * Deduced "Patient Orientation" will be "AL\F"
+ * (main X axis orientation is towards patient's nose, and a little bit towards the left)
+ * but the image looks *perfectly* sagital (for the head, not for the patient) !
+ *
+ * Imagine the patient's stiffneck causes head to be *bended* 30 degrees towards the left AND *turned* left.
+ * Sagital images are requested...
+ * You'll probabely have 3 letters for X axis and  Y axis, and the image remains *perfectly* sagital !
+ * The values are given within the 'Patient referential', *not* within the 'Organ referential' ...
+ */
+
+class GDCM_EXPORT Orientation : public Base
+{
+public:
+  Orientation() {}
+  ~Orientation() {}
+
+  OrientationType GetOrientationType( File *file );
+  std::string GetOrientation ( File *file );  
+  
+  static const char* GetOrientationTypeString(OrientationType const o);
+
+private:
+   Res VerfCriterion(int typeCriterion, double criterionNew, Res const &res);
+   double CalculLikelyhood2Vec(vector3D const &refA, vector3D const &refB, 
+                               vector3D const &ori1, vector3D const &ori2);
+   vector3D ProductVectorial(vector3D const &vec1, vector3D const &vec2);
+   std::string GetSingleOrientation ( float *iop);
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmPixelReadConvert.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmPixelReadConvert.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6f73af3275d4904b8d650e878890e84c556196d8
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmPixelReadConvert.cxx
@@ -0,0 +1,1508 @@
+/*=========================================================================
+ 
+  Program:   gdcm
+  Module:    $RCSfile: gdcmPixelReadConvert.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.6 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmPixelReadConvert.h"
+#include "gdcmDebug.h"
+#include "gdcmFile.h"
+#include "gdcmGlobal.h"
+#include "gdcmTS.h"
+#include "gdcmDocEntry.h"
+#include "gdcmRLEFramesInfo.h"
+#include "gdcmJPEGFragmentsInfo.h"
+
+#include <fstream>
+#include <stdio.h> //for sscanf
+
+#if defined(__BORLANDC__)
+   #include <mem.h> // for memset
+#endif 
+
+namespace gdcm
+{
+
+//bool ReadMPEGFile (std::ifstream *fp, void *image_buffer, size_t lenght);
+bool gdcm_read_JPEG2000_file (void* raw, 
+                              char *inputdata, size_t inputlength);
+//-----------------------------------------------------------------------------
+#define str2num(str, typeNum) *((typeNum *)(str))
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/// Constructor
+PixelReadConvert::PixelReadConvert() 
+{
+   RGB          = 0;
+   RGBSize      = 0;
+   Raw          = 0;
+   RawSize      = 0;
+   LutRGBA      = 0;
+   LutRedData   = 0;
+   LutGreenData = 0;
+   LutBlueData  = 0;
+   RLEInfo      = 0;
+   JPEGInfo     = 0;
+   UserFunction = 0;
+   FileInternal = 0;
+}
+
+/// Canonical Destructor
+PixelReadConvert::~PixelReadConvert() 
+{
+   Squeeze();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief Predicate to know whether the image[s] (once Raw) is RGB.
+ * \note See comments of \ref ConvertHandleColor
+ */
+bool PixelReadConvert::IsRawRGB()
+{
+   if (   IsMonochrome
+       || PlanarConfiguration == 2
+       || IsPaletteColor )
+   {
+      return false;
+   }
+   return true;
+}
+/**
+ * \brief Gets various usefull informations from the file header
+ * @param file gdcm::File pointer
+ */
+void PixelReadConvert::GrabInformationsFromFile( File *file )
+{
+   // Number of Bits Allocated for storing a Pixel is defaulted to 16
+   // when absent from the file.
+   BitsAllocated = file->GetBitsAllocated();
+   if ( BitsAllocated == 0 )
+   {
+      BitsAllocated = 16;
+   }
+
+   // Number of "Bits Stored", defaulted to number of "Bits Allocated"
+   // when absent from the file.
+   BitsStored = file->GetBitsStored();
+   if ( BitsStored == 0 )
+   {
+      BitsStored = BitsAllocated;
+   }
+
+   // High Bit Position, defaulted to "Bits Allocated" - 1
+   HighBitPosition = file->GetHighBitPosition();
+   if ( HighBitPosition == 0 )
+   {
+      HighBitPosition = BitsAllocated - 1;
+   }
+
+   XSize           = file->GetXSize();
+   YSize           = file->GetYSize();
+   ZSize           = file->GetZSize();
+   SamplesPerPixel = file->GetSamplesPerPixel();
+   //PixelSize       = file->GetPixelSize();  Useless
+   PixelSign       = file->IsSignedPixelData();
+   SwapCode        = file->GetSwapCode();
+
+   IsPrivateGETransferSyntax = IsMPEG
+             = IsJPEG2000 = IsJPEGLS = IsJPEGLossy  
+             = IsJPEGLossless = IsRLELossless 
+             = false;
+
+   std::string ts  = file->GetTransferSyntax();
+   IsRaw =
+        ( ! file->IsDicomV3() )
+     || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian
+     || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE
+     || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian
+     || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian
+     || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian;
+
+   IsMPEG          = Global::GetTS()->IsMPEG(ts);
+   IsJPEG2000      = Global::GetTS()->IsJPEG2000(ts);
+   IsJPEGLS        = Global::GetTS()->IsJPEGLS(ts);
+   IsJPEGLossy     = Global::GetTS()->IsJPEGLossy(ts);
+   IsJPEGLossless  = Global::GetTS()->IsJPEGLossless(ts);
+   IsRLELossless   = Global::GetTS()->IsRLELossless(ts);
+
+   PixelOffset     = file->GetPixelOffset();
+   PixelDataLength = file->GetPixelAreaLength();
+   RLEInfo         = file->GetRLEInfo();
+   JPEGInfo        = file->GetJPEGInfo();
+
+   IsMonochrome    = file->IsMonochrome();
+   IsMonochrome1   = file->IsMonochrome1();
+   IsPaletteColor  = file->IsPaletteColor();
+   IsYBRFull       = file->IsYBRFull();
+
+   PlanarConfiguration = file->GetPlanarConfiguration();
+
+   /////////////////////////////////////////////////////////////////
+   // LUT section:
+   HasLUT = file->HasLUT();
+   if ( HasLUT )
+   {
+      // Just in case some access to a File element requires disk access.
+      LutRedDescriptor   = file->GetEntryValue( 0x0028, 0x1101 );
+      LutGreenDescriptor = file->GetEntryValue( 0x0028, 0x1102 );
+      LutBlueDescriptor  = file->GetEntryValue( 0x0028, 0x1103 );
+   
+      // FIXME : The following comment is probabely meaningless, since LUT are *always*
+      // loaded at parsing time, whatever their length is.
+         
+      // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
+      // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
+      // Document::Document() ], the loading of the value (content) of a
+      // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
+      // loaded). Hence, we first try to obtain the LUTs data from the file
+      // and when this fails we read the LUTs data directly from disk.
+      // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
+      //       We should NOT bypass the [Bin|Val]Entry class. Instead
+      //       an access to an UNLOADED content of a [Bin|Val]Entry occurence
+      //       (e.g. BinEntry::GetBinArea()) should force disk access from
+      //       within the [Bin|Val]Entry class itself. The only problem
+      //       is that the [Bin|Val]Entry is unaware of the FILE* is was
+      //       parsed from. Fix that. FIXME.
+   
+      // //// Red round
+      file->LoadEntryBinArea(0x0028, 0x1201);
+      LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
+      if ( ! LutRedData )
+      {
+         gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
+      }
+
+      // //// Green round:
+      file->LoadEntryBinArea(0x0028, 0x1202);
+      LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
+      if ( ! LutGreenData)
+      {
+         gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
+      }
+
+      // //// Blue round:
+      file->LoadEntryBinArea(0x0028, 0x1203);
+      LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
+      if ( ! LutBlueData )
+      {
+         gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
+      }
+   }
+   FileInternal = file;   
+
+   ComputeRawAndRGBSizes();
+}
+
+/// \brief Reads from disk and decompresses Pixels
+bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
+{
+   // ComputeRawAndRGBSizes is already made by 
+   // ::GrabInformationsFromfile. So, the structure sizes are
+   // correct
+   Squeeze();
+
+   //////////////////////////////////////////////////
+   //// First stage: get our hands on the Pixel Data.
+   if ( !fp )
+   {
+      gdcmWarningMacro( "Unavailable file pointer." );
+      return false;
+   }
+
+   fp->seekg( PixelOffset, std::ios::beg );
+   if ( fp->fail() || fp->eof() )
+   {
+      gdcmWarningMacro( "Unable to find PixelOffset in file." );
+      return false;
+   }
+
+   AllocateRaw();
+
+   //////////////////////////////////////////////////
+   //// Second stage: read from disk and decompress.
+   if ( BitsAllocated == 12 ) // We suppose 'BitsAllocated' = 12 only exist for uncompressed files
+   {
+      ReadAndDecompress12BitsTo16Bits( fp);
+   }
+   else if ( IsRaw )
+   {
+      // This problem can be found when some obvious informations are found
+      // after the field containing the image data. In this case, these
+      // bad data are added to the size of the image (in the PixelDataLength
+      // variable). But RawSize is the right size of the image !
+      if ( PixelDataLength != RawSize )
+      {
+         gdcmWarningMacro( "Mismatch between PixelReadConvert : "
+                            << PixelDataLength << " and RawSize : " << RawSize );
+      }
+      if ( PixelDataLength > RawSize )
+      {
+         fp->read( (char*)Raw, RawSize);
+      }
+      else
+      {
+         fp->read( (char*)Raw, PixelDataLength);
+      }
+
+      if ( fp->fail() || fp->eof())
+      {
+         gdcmWarningMacro( "Reading of Raw pixel data failed." );
+         return false;
+      }
+   } 
+   else if ( IsRLELossless )
+   {
+      if ( ! RLEInfo->DecompressRLEFile
+                               ( fp, Raw, XSize, YSize, ZSize, BitsAllocated ) )
+      {
+         gdcmWarningMacro( "RLE decompressor failed." );
+         return false;
+      }
+   }
+   else if ( IsMPEG )
+   {
+      //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
+      //return false;
+      // fp has already been seek to start of mpeg
+      //ReadMPEGFile(fp, (char*)Raw, PixelDataLength); 
+      return true;
+   }
+   else
+   {
+      // Default case concerns JPEG family
+      if ( ! ReadAndDecompressJPEGFile( fp ) )
+      {
+         gdcmWarningMacro( "JPEG decompressor ( ReadAndDecompressJPEGFile()"
+                              << " method ) failed." );
+         return false;
+      }
+   }
+
+   ////////////////////////////////////////////
+   //// Third stage: twigle the bytes and bits.
+   ConvertReorderEndianity();
+   ConvertReArrangeBits();
+   ConvertFixGreyLevels();
+   if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
+      UserFunction( Raw, FileInternal);
+   ConvertHandleColor();
+
+   return true;
+}
+
+/// Deletes Pixels Area
+void PixelReadConvert::Squeeze() 
+{
+   if ( RGB )
+      delete [] RGB;
+   RGB = 0;
+
+   if ( Raw )
+      delete [] Raw;
+   Raw = 0;
+
+   if ( LutRGBA )
+      delete [] LutRGBA;
+   LutRGBA = 0;
+}
+
+/**
+ * \brief Build the RGB image from the Raw image and the LUTs.
+ */
+bool PixelReadConvert::BuildRGBImage()
+{
+   if ( RGB )
+   {
+      // The job is already done.
+      return true;
+   }
+
+   if ( ! Raw )
+   {
+      // The job can't be done
+      return false;
+   }
+
+   BuildLUTRGBA();
+   if ( ! LutRGBA )
+   {
+      // The job can't be done
+      return false;
+   }
+
+   gdcmDebugMacro( "--> BuildRGBImage" );
+                                                                                
+   // Build RGB Pixels
+   AllocateRGB();
+   
+   int j;
+   if ( BitsAllocated <= 8 )
+   {
+      uint8_t *localRGB = RGB;
+      for (size_t i = 0; i < RawSize; ++i )
+      {
+         j  = Raw[i] * 4;
+         *localRGB++ = LutRGBA[j];
+         *localRGB++ = LutRGBA[j+1];
+         *localRGB++ = LutRGBA[j+2];
+      }
+    }
+ 
+    else  // deal with 16 bits pixels and 16 bits Palette color
+    {
+      uint16_t *localRGB = (uint16_t *)RGB;
+      for (size_t i = 0; i < RawSize/2; ++i )
+      {
+         j  = ((uint16_t *)Raw)[i] * 4;
+         *localRGB++ = ((uint16_t *)LutRGBA)[j];
+         *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
+         *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
+      } 
+    }
+ 
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \brief Read from file a 12 bits per pixel image and decompress it
+ *        into a 16 bits per pixel image.
+ */
+void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
+               throw ( FormatError )
+{
+   int nbPixels = XSize * YSize;
+   uint16_t *localDecompres = (uint16_t*)Raw;
+
+   for( int p = 0; p < nbPixels; p += 2 )
+   {
+      uint8_t b0, b1, b2;
+
+      fp->read( (char*)&b0, 1);
+      if ( fp->fail() || fp->eof() )
+      {
+         throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
+                                "Unfound first block" );
+      }
+
+      fp->read( (char*)&b1, 1 );
+      if ( fp->fail() || fp->eof())
+      {
+         throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
+                                "Unfound second block" );
+      }
+
+      fp->read( (char*)&b2, 1 );
+      if ( fp->fail() || fp->eof())
+      {
+         throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
+                                "Unfound second block" );
+      }
+
+      // Two steps are necessary to please VC++
+      //
+      // 2 pixels 12bit =     [0xABCDEF]
+      // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
+      //                        A                     B                 D
+      *localDecompres++ =  ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
+      //                        F                     C                 E
+      *localDecompres++ =  ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
+
+      /// \todo JPR Troubles expected on Big-Endian processors ?
+   }
+}
+
+/**
+ * \brief     Reads from disk the Pixel Data of JPEG Dicom encapsulated
+ *            file and decompress it.
+ * @param     fp File Pointer
+ * @return    Boolean
+ */
+bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
+{
+   if ( IsJPEG2000 )
+   {
+     // make sure this is the right JPEG compression
+     assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEGLS );
+     // FIXME this is really ugly but it seems I have to load the complete
+     // jpeg2000 stream to use jasper:
+     // I don't think we'll ever be able to deal with multiple fragments properly
+
+      unsigned long inputlength = 0;
+      JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
+      while( jpegfrag )
+      {
+         inputlength += jpegfrag->GetLength();
+         jpegfrag = JPEGInfo->GetNextFragment();
+      }
+      gdcmAssertMacro( inputlength != 0);
+      uint8_t *inputdata = new uint8_t[inputlength];
+      char *pinputdata = (char*)inputdata;
+      jpegfrag = JPEGInfo->GetFirstFragment();
+      while( jpegfrag )
+      {
+         fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
+         fp->read(pinputdata, jpegfrag->GetLength());
+         pinputdata += jpegfrag->GetLength();
+         jpegfrag = JPEGInfo->GetNextFragment();
+      }
+      // Warning the inputdata buffer is delete in the function
+      if ( ! gdcm_read_JPEG2000_file( Raw, 
+          (char*)inputdata, inputlength ) )
+      {
+         return true;
+      }
+      // wow what happen, must be an error
+      gdcmWarningMacro( "gdcm_read_JPEG2000_file() failed "); 
+      return false;
+   }
+   else if ( IsJPEGLS )
+   {
+     // make sure this is the right JPEG compression
+     assert( !IsJPEGLossless || !IsJPEGLossy || !IsJPEG2000 );
+   // WARNING : JPEG-LS is NOT the 'classical' Jpeg Lossless : 
+   // [JPEG-LS is the basis for new lossless/near-lossless compression
+   // standard for continuous-tone images intended for JPEG2000. The standard
+   // is based on the LOCO-I algorithm (LOw COmplexity LOssless COmpression
+   // for Images) developed at Hewlett-Packard Laboratories]
+   //
+   // see http://datacompression.info/JPEGLS.shtml
+   //
+#if 0
+   std::cerr << "count:" << JPEGInfo->GetFragmentCount() << std::endl;
+      unsigned long inputlength = 0;
+      JPEGFragment *jpegfrag = JPEGInfo->GetFirstFragment();
+      while( jpegfrag )
+      {
+         inputlength += jpegfrag->GetLength();
+         jpegfrag = JPEGInfo->GetNextFragment();
+      }
+      gdcmAssertMacro( inputlength != 0);
+      uint8_t *inputdata = new uint8_t[inputlength];
+      char *pinputdata = (char*)inputdata;
+      jpegfrag = JPEGInfo->GetFirstFragment();
+      while( jpegfrag )
+      {
+         fp->seekg( jpegfrag->GetOffset(), std::ios::beg);
+         fp->read(pinputdata, jpegfrag->GetLength());
+         pinputdata += jpegfrag->GetLength();
+         jpegfrag = JPEGInfo->GetNextFragment();
+      }  
+      
+  //fp->read((char*)Raw, PixelDataLength);
+
+  std::ofstream out("/tmp/jpegls.jpg");
+  out.write((char*)inputdata, inputlength);
+  out.close();
+  delete[] inputdata;
+#endif
+
+      gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
+      fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
+//    if ( ! gdcm_read_JPEGLS_file( fp,Raw ) )
+         return false;
+   }
+   else
+   {
+     // make sure this is the right JPEG compression
+     assert( !IsJPEGLS || !IsJPEG2000 );
+     // Precompute the offset localRaw will be shifted with
+     int length = XSize * YSize * SamplesPerPixel;
+     int numberBytes = BitsAllocated / 8;
+
+     JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
+     return true;
+   }
+}
+
+/**
+ * \brief Build Red/Green/Blue/Alpha LUT from File when :
+ *         - (0028,0004) : Photometric Interpretation == [PALETTE COLOR ]
+ *         and
+ *         - (0028,1101),(0028,1102),(0028,1102)
+ *            xxx Palette Color Lookup Table Descriptor are found
+ *          and
+ *         - (0028,1201),(0028,1202),(0028,1202)
+ *           xxx Palette Color Lookup Table Data - are found
+ * \warning does NOT deal with :
+ *   - 0028 1100 Gray Lookup Table Descriptor (Retired)
+ *   - 0028 1221 Segmented Red Palette Color Lookup Table Data
+ *   - 0028 1222 Segmented Green Palette Color Lookup Table Data
+ *   - 0028 1223 Segmented Blue Palette Color Lookup Table Data
+ *   no known Dicom reader deals with them :-(
+ * @return a RGBA Lookup Table
+ */
+void PixelReadConvert::BuildLUTRGBA()
+{
+
+   // Note to code reviewers :
+   // The problem is *much more* complicated, since a lot of manufacturers
+   // Don't follow the norm :
+   // have a look at David Clunie's remark at the end of this .cxx file.
+   if ( LutRGBA )
+   
+   {
+      return;
+   }
+   // Not so easy : see
+   // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
+                                                                                
+   if ( ! IsPaletteColor )
+   {
+      return;
+   }
+                                                                                
+   if (   LutRedDescriptor   == GDCM_UNFOUND
+       || LutGreenDescriptor == GDCM_UNFOUND
+       || LutBlueDescriptor  == GDCM_UNFOUND )
+   {
+      gdcmWarningMacro( "(At least) a LUT Descriptor is missing" );
+      return;
+   }
+
+   ////////////////////////////////////////////
+   // Extract the info from the LUT descriptors
+   int lengthR;   // Red LUT length in Bytes
+   int debR;      // Subscript of the first Lut Value
+   int nbitsR;    // Lut item size (in Bits)
+   int nbRead;    // nb of items in LUT descriptor (must be = 3)
+
+   nbRead = sscanf( LutRedDescriptor.c_str(),
+                        "%d\\%d\\%d",
+                        &lengthR, &debR, &nbitsR );
+   if ( nbRead != 3 )
+   {
+      gdcmWarningMacro( "Wrong Red LUT descriptor" );
+   }                                                                                
+   int lengthG;  // Green LUT length in Bytes
+   int debG;     // Subscript of the first Lut Value
+   int nbitsG;   // Lut item size (in Bits)
+
+   nbRead = sscanf( LutGreenDescriptor.c_str(),
+                    "%d\\%d\\%d",
+                    &lengthG, &debG, &nbitsG );  
+   if ( nbRead != 3 )
+   {
+      gdcmWarningMacro( "Wrong Green LUT descriptor" );
+   }
+                                                                                
+   int lengthB;  // Blue LUT length in Bytes
+   int debB;     // Subscript of the first Lut Value
+   int nbitsB;   // Lut item size (in Bits)
+   nbRead = sscanf( LutRedDescriptor.c_str(),
+                    "%d\\%d\\%d",
+                    &lengthB, &debB, &nbitsB );
+   if ( nbRead != 3 )
+   {
+      gdcmWarningMacro( "Wrong Blue LUT descriptor" );
+   }
+ 
+   gdcmDebugMacro(" lengthR " << lengthR << " debR " 
+                << debR << " nbitsR " << nbitsR);
+   gdcmDebugMacro(" lengthG " << lengthG << " debG " 
+                << debG << " nbitsG " << nbitsG);
+   gdcmDebugMacro(" lengthB " << lengthB << " debB " 
+                << debB << " nbitsB " << nbitsB);
+
+   if ( !lengthR ) // if = 2^16, this shall be 0 see : CP-143
+      lengthR=65536;
+   if ( !lengthG ) // if = 2^16, this shall be 0
+      lengthG=65536;
+   if ( !lengthB ) // if = 2^16, this shall be 0
+      lengthB=65536; 
+                                                                                
+   ////////////////////////////////////////////////////////
+
+   if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
+   {
+      gdcmWarningMacro( "(At least) a LUT is missing" );
+      return;
+   }
+
+   // -------------------------------------------------------------
+   
+   if ( BitsAllocated <= 8 )
+   {
+      // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
+      LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
+      if ( !LutRGBA )
+         return;
+      LutItemNumber = 256;
+      LutItemSize   = 8;
+      memset( LutRGBA, 0, 1024 );
+                                                                                
+      int mult;
+      if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
+      {
+         // when LUT item size is different than pixel size
+         mult = 2; // high byte must be = low byte
+      }
+      else
+      {
+         // See PS 3.3-2003 C.11.1.1.2 p 619
+         mult = 1;
+      }
+                                                                                
+      // if we get a black image, let's just remove the '+1'
+      // from 'i*mult+1' and check again
+      // if it works, we shall have to check the 3 Palettes
+      // to see which byte is ==0 (first one, or second one)
+      // and fix the code
+      // We give up the checking to avoid some (useless ?) overhead
+      // (optimistic asumption)
+      int i;
+      uint8_t *a;
+
+      //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
+
+      //FIXME :  +1 : to get 'low value' byte
+      //         Trouble expected on Big Endian Processors ?
+      //         16 BIts Per Pixel Palette Color to be swapped?
+
+      a = LutRGBA + 0 + debR;
+      for( i=0; i < lengthR; ++i )
+      {
+         *a = LutRedData[i*mult+1]; 
+         a += 4;
+      }
+                                                                                
+      a = LutRGBA + 1 + debG;
+      for( i=0; i < lengthG; ++i)
+      {
+         *a = LutGreenData[i*mult+1];
+         a += 4;
+      }
+                                                                                
+      a = LutRGBA + 2 + debB;
+      for(i=0; i < lengthB; ++i)
+      {
+         *a = LutBlueData[i*mult+1];
+         a += 4;
+      }
+                                    
+      a = LutRGBA + 3 ;
+      for(i=0; i < 256; ++i)
+      {
+         *a = 1; // Alpha component
+         a += 4;
+      }
+   }
+   else
+   {
+      // Probabely the same stuff is to be done for 16 Bits Pixels
+      // with 65536 entries LUT ?!?
+      // Still looking for accurate info on the web :-(
+
+      gdcmWarningMacro( "Sorry Palette Color Lookup Tables not yet dealt with"
+                         << " for 16 Bits Per Pixel images" );
+
+      // forge the 4 * 16 Bits Red/Green/Blue/Alpha LUT
+
+      LutRGBA = (uint8_t *)new uint16_t[ 65536*4 ]; // 2^16 * 4 (R, G, B, Alpha)
+      if ( !LutRGBA )
+         return;
+      memset( LutRGBA, 0, 65536*4*2 );  // 16 bits = 2 bytes ;-)
+
+      LutItemNumber = 65536;
+      LutItemSize   = 16;
+
+      int i;
+      uint16_t *a16;
+
+      //take "Subscript of the first Lut Value" (debR,debG,debB) into account!
+
+      a16 = (uint16_t*)LutRGBA + 0 + debR;
+      for( i=0; i < lengthR; ++i )
+      {
+         *a16 = ((uint16_t*)LutRedData)[i];
+         a16 += 4;
+      }
+                                                                              
+      a16 = (uint16_t*)LutRGBA + 1 + debG;
+      for( i=0; i < lengthG; ++i)
+      {
+         *a16 = ((uint16_t*)LutGreenData)[i];
+         a16 += 4;
+      }
+                                                                                
+      a16 = (uint16_t*)LutRGBA + 2 + debB;
+      for(i=0; i < lengthB; ++i)
+      {
+         *a16 = ((uint16_t*)LutBlueData)[i];
+         a16 += 4;
+      }
+                                                                             
+      a16 = (uint16_t*)LutRGBA + 3 ;
+      for(i=0; i < 65536; ++i)
+      {
+         *a16 = 1; // Alpha component
+         a16 += 4;
+      }
+/* Just to 'see' the LUT, at debug time
+// Don't remove this commented out code.
+
+      a16=(uint16_t*)LutRGBA;
+      for (int j=0;j<65536;j++)
+      {
+         std::cout << *a16     << " " << *(a16+1) << " "
+                   << *(a16+2) << " " << *(a16+3) << std::endl;
+         a16+=4;
+      }
+*/
+   }
+}
+
+/**
+ * \brief Swap the bytes, according to \ref SwapCode.
+ */
+void PixelReadConvert::ConvertSwapZone()
+{
+   unsigned int i;
+
+   // If this file is 'ImplicitVR BigEndian PrivateGE Transfer Syntax', 
+   // then the header is in little endian format and the pixel data is in 
+   // big endian format.  When reading the header, GDCM has already established
+   // a byte swapping code suitable for this machine to read the
+   // header. In TS::ImplicitVRBigEndianPrivateGE, this code will need
+   // to be switched in order to read the pixel data.  This must be
+   // done REGARDLESS of the processor endianess!
+   //
+   // Example:  Assume we are on a little endian machine.  When
+   // GDCM reads the header, the header will match the machine
+   // endianess and the swap code will be established as a no-op.
+   // When GDCM reaches the pixel data, it will need to switch the
+   // swap code to do big endian to little endian conversion.
+   //
+   // Now, assume we are on a big endian machine.  When GDCM reads the
+   // header, the header will be recognized as a different endianess
+   // than the machine endianess, and a swap code will be established
+   // to convert from little endian to big endian.  When GDCM readers
+   // the pixel data, the pixel data endianess will now match the
+   // machine endianess.  But we currently have a swap code that
+   // converts from little endian to big endian.  In this case, we
+   // need to switch the swap code to a no-op.
+   //
+   // Therefore, in either case, if the file is in
+   // 'ImplicitVR BigEndian PrivateGE Transfer Syntax', then GDCM needs to switch
+   // the byte swapping code when entering the pixel data.
+   
+   int tempSwapCode = SwapCode;
+   if ( IsPrivateGETransferSyntax )
+   {
+      gdcmWarningMacro(" IsPrivateGETransferSyntax found; turn the SwapCode"); 
+      // PrivateGETransferSyntax only exists for 'true' Dicom images
+      // we assume there is no 'exotic' 32 bits endianess!
+      if (SwapCode == 1234) 
+      {
+         tempSwapCode = 4321;
+      }
+      else if (SwapCode == 4321)
+      {
+         tempSwapCode = 1234;
+      }
+   }
+    
+   if ( BitsAllocated == 16 )
+   {
+      uint16_t *im16 = (uint16_t*)Raw;
+      switch( tempSwapCode )
+      {
+         case 1234:
+            break;
+         case 3412:
+         case 2143:
+         case 4321:
+            for( i = 0; i < RawSize / 2; i++ )
+            {
+               im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
+            }
+            break;
+         default:
+            gdcmWarningMacro("SwapCode value (16 bits) not allowed." 
+                        << tempSwapCode);
+      }
+   }
+   else if ( BitsAllocated == 32 )
+   {
+      uint32_t s32;
+      uint16_t high;
+      uint16_t low;
+      uint32_t *im32 = (uint32_t*)Raw;
+      switch ( tempSwapCode )
+      {
+         case 1234:
+            break;
+         case 4321:
+            for( i = 0; i < RawSize / 4; i++ )
+            {
+               low     = im32[i] & 0x0000ffff;  // 4321
+               high    = im32[i] >> 16;
+               high    = ( high >> 8 ) | ( high << 8 );
+               low     = ( low  >> 8 ) | ( low  << 8 );
+               s32     = low;
+               im32[i] = ( s32 << 16 ) | high;
+            }
+            break;
+         case 2143:
+            for( i = 0; i < RawSize / 4; i++ )
+            {
+               low     = im32[i] & 0x0000ffff;   // 2143
+               high    = im32[i] >> 16;
+               high    = ( high >> 8 ) | ( high << 8 );
+               low     = ( low  >> 8 ) | ( low  << 8 );
+               s32     = high;
+               im32[i] = ( s32 << 16 ) | low;
+            }
+            break;
+         case 3412:
+            for( i = 0; i < RawSize / 4; i++ )
+            {
+               low     = im32[i] & 0x0000ffff; // 3412
+               high    = im32[i] >> 16;
+               s32     = low;
+               im32[i] = ( s32 << 16 ) | high;
+            }
+            break;
+         default:
+            gdcmWarningMacro("SwapCode value (32 bits) not allowed." << tempSwapCode );
+      }
+   }
+}
+
+/**
+ * \brief Deal with endianness i.e. re-arange bytes inside the integer
+ */
+void PixelReadConvert::ConvertReorderEndianity()
+{
+   if ( BitsAllocated != 8 )
+   {
+      ConvertSwapZone();
+   }
+
+   // Special kludge in order to deal with xmedcon broken images:
+   if ( BitsAllocated == 16
+     && BitsStored < BitsAllocated
+     && !PixelSign )
+   {
+      int l = (int)( RawSize / ( BitsAllocated / 8 ) );
+      uint16_t *deb = (uint16_t *)Raw;
+      for(int i = 0; i<l; i++)
+      {
+         if ( *deb == 0xffff )
+         {
+           *deb = 0;
+         }
+         deb++;
+      }
+   }
+}
+
+/**
+ * \brief Deal with Grey levels i.e. re-arange them
+ *        to have low values = dark, high values = bright
+ */
+void PixelReadConvert::ConvertFixGreyLevels()
+{
+   if (!IsMonochrome1)
+      return;
+
+   uint32_t i; // to please M$VC6
+   int16_t j;
+
+   if (!PixelSign)
+   {
+      if ( BitsAllocated == 8 )
+      {
+         uint8_t *deb = (uint8_t *)Raw;
+         for (i=0; i<RawSize; i++)      
+         {
+            *deb = 255 - *deb;
+            deb++;
+         }
+         return;
+      }
+
+      if ( BitsAllocated == 16 )
+      {
+         uint16_t mask =1;
+         for (j=0; j<BitsStored-1; j++)
+         {
+            mask = (mask << 1) +1; // will be fff when BitsStored=12
+         }
+
+         uint16_t *deb = (uint16_t *)Raw;
+         for (i=0; i<RawSize/2; i++)      
+         {
+            *deb = mask - *deb;
+            deb++;
+         }
+         return;
+       }
+   }
+   else
+   {
+      if ( BitsAllocated == 8 )
+      {
+         uint8_t smask8 = 255;
+         uint8_t *deb = (uint8_t *)Raw;
+         for (i=0; i<RawSize; i++)      
+         {
+            *deb = smask8 - *deb;
+            deb++;
+         }
+         return;
+      }
+      if ( BitsAllocated == 16 )
+      {
+         uint16_t smask16 = 65535;
+         uint16_t *deb = (uint16_t *)Raw;
+         for (i=0; i<RawSize/2; i++)      
+         {
+            *deb = smask16 - *deb;
+            deb++;
+         }
+         return;
+      }
+   }
+}
+
+/**
+ * \brief  Re-arrange the bits within the bytes.
+ * @return Boolean always true
+ */
+bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
+{
+
+   if ( BitsStored != BitsAllocated )
+   {
+      int l = (int)( RawSize / ( BitsAllocated / 8 ) );
+      if ( BitsAllocated == 16 )
+      {
+         // pmask : to mask the 'unused bits' (may contain overlays)
+         uint16_t pmask = 0xffff;
+         pmask = pmask >> ( BitsAllocated - BitsStored );
+
+         uint16_t *deb = (uint16_t*)Raw;
+
+         if ( !PixelSign )  // Pixels are unsigned
+         {
+            for(int i = 0; i<l; i++)
+            {   
+               *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
+               deb++;
+            }
+         }
+         else // Pixels are signed
+         {
+            // smask : to check the 'sign' when BitsStored != BitsAllocated
+            uint16_t smask = 0x0001;
+            smask = smask << ( 16 - (BitsAllocated - BitsStored + 1) );
+            // nmask : to propagate sign bit on negative values
+            int16_t nmask = (int16_t)0x8000;  
+            nmask = nmask >> ( BitsAllocated - BitsStored - 1 );
+ 
+            for(int i = 0; i<l; i++)
+            {
+               *deb = *deb >> (BitsStored - HighBitPosition - 1);
+               if ( *deb & smask )
+               {
+                  *deb = *deb | nmask;
+               }
+               else
+               {
+                  *deb = *deb & pmask;
+               }
+               deb++;
+            }
+         }
+      }
+      else if ( BitsAllocated == 32 )
+      {
+         // pmask : to mask the 'unused bits' (may contain overlays)
+         uint32_t pmask = 0xffffffff;
+         pmask = pmask >> ( BitsAllocated - BitsStored );
+
+         uint32_t *deb = (uint32_t*)Raw;
+
+         if ( !PixelSign )
+         {
+            for(int i = 0; i<l; i++)
+            {             
+               *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & pmask;
+               deb++;
+            }
+         }
+         else
+         {
+            // smask : to check the 'sign' when BitsStored != BitsAllocated
+            uint32_t smask = 0x00000001;
+            smask = smask >> ( 32 - (BitsAllocated - BitsStored +1 ));
+            // nmask : to propagate sign bit on negative values
+            int32_t nmask = 0x80000000;   
+            nmask = nmask >> ( BitsAllocated - BitsStored -1 );
+
+            for(int i = 0; i<l; i++)
+            {
+               *deb = *deb >> (BitsStored - HighBitPosition - 1);
+               if ( *deb & smask )
+                  *deb = *deb | nmask;
+               else
+                  *deb = *deb & pmask;
+               deb++;
+            }
+         }
+      }
+      else
+      {
+         gdcmWarningMacro("Weird image (BitsAllocated !=8, 12, 16, 32)");
+         throw FormatError( "Weird image !?" );
+      }
+   }
+   return true;
+}
+
+/**
+ * \brief   Convert (Red plane, Green plane, Blue plane) to RGB pixels
+ * \warning Works on all the frames at a time
+ */
+void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
+{
+   gdcmWarningMacro("--> ConvertRGBPlanesToRGBPixels");
+
+   uint8_t *localRaw = Raw;
+   uint8_t *copyRaw = new uint8_t[ RawSize ];
+   memmove( copyRaw, localRaw, RawSize );
+
+   int l = XSize * YSize * ZSize;
+
+   uint8_t *a = copyRaw;
+   uint8_t *b = copyRaw + l;
+   uint8_t *c = copyRaw + l + l;
+
+   for (int j = 0; j < l; j++)
+   {
+      *(localRaw++) = *(a++);
+      *(localRaw++) = *(b++);
+      *(localRaw++) = *(c++);
+   }
+   delete[] copyRaw;
+}
+
+/**
+ * \brief   Convert (cY plane, cB plane, cR plane) to RGB pixels
+ * \warning Works on all the frames at a time
+ */
+void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
+{
+  // Remarks for YBR newbees :
+  // YBR_FULL works very much like RGB, i.e. three samples per pixel, 
+  // just the color space is YCbCr instead of RGB. This is particularly useful
+  // for doppler ultrasound where most of the image is grayscale 
+  // (i.e. only populates the Y components) and Cb and Cr are mostly zero,
+  // except for the few patches of color on the image.
+  // On such images, RLE achieves a compression ratio that is much better 
+  // than the compression ratio on an equivalent RGB image. 
+ 
+   gdcmWarningMacro("--> ConvertYcBcRPlanesToRGBPixels");
+   
+   uint8_t *localRaw = Raw;
+   uint8_t *copyRaw = new uint8_t[ RawSize ];
+   memmove( copyRaw, localRaw, RawSize );
+
+   // to see the tricks about YBR_FULL, YBR_FULL_422,
+   // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
+   // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
+   // and be *very* affraid
+   //
+   int l        = XSize * YSize;
+   int nbFrames = ZSize;
+
+   uint8_t *a = copyRaw + 0;
+   uint8_t *b = copyRaw + l;
+   uint8_t *c = copyRaw + l+ l;
+   int32_t R, G, B;
+
+   ///  We replaced easy to understand but time consuming floating point
+   ///  computations by the 'well known' integer computation counterpart
+   ///  Refer to :
+   ///            http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
+   ///  for code optimisation.
+
+   for ( int i = 0; i < nbFrames; i++ )
+   {
+      for ( int j = 0; j < l; j++ )
+      {
+         R = 38142 *(*a-16) + 52298 *(*c -128);
+         G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128);
+         B = 38142 *(*a-16) + 66093 *(*b -128);
+
+         R = (R+16384)>>15;
+         G = (G+16384)>>15;
+         B = (B+16384)>>15;
+
+         if (R < 0)   R = 0;
+         if (G < 0)   G = 0;
+         if (B < 0)   B = 0;
+         if (R > 255) R = 255;
+         if (G > 255) G = 255;
+         if (B > 255) B = 255;
+
+         *(localRaw++) = (uint8_t)R;
+         *(localRaw++) = (uint8_t)G;
+         *(localRaw++) = (uint8_t)B;
+         a++;
+         b++;
+         c++;
+      }
+   }
+   delete[] copyRaw;
+}
+
+/// \brief Deals with the color decoding i.e. handle:
+///   - R, G, B planes (as opposed to RGB pixels)
+///   - YBR (various) encodings.
+///   - LUT[s] (or "PALETTE COLOR").
+
+void PixelReadConvert::ConvertHandleColor()
+{
+   //////////////////////////////////
+   // Deal with the color decoding i.e. handle:
+   //   - R, G, B planes (as opposed to RGB pixels)
+   //   - YBR (various) encodings.
+   //   - LUT[s] (or "PALETTE COLOR").
+   //
+   // The classification in the color decoding schema is based on the blending
+   // of two Dicom tags values:
+   // * "Photometric Interpretation" for which we have the cases:
+   //  - [Photo A] MONOCHROME[1|2] pictures,
+   //  - [Photo B] RGB or YBR_FULL_422 (which acts as RGB),
+   //  - [Photo C] YBR_* (with the above exception of YBR_FULL_422)
+   //  - [Photo D] "PALETTE COLOR" which indicates the presence of LUT[s].
+   // * "Planar Configuration" for which we have the cases:
+   //  - [Planar 0] 0 then Pixels are already RGB
+   //  - [Planar 1] 1 then we have 3 planes : R, G, B,
+   //  - [Planar 2] 2 then we have 1 gray Plane and 3 LUTs
+   //
+   // Now in theory, one could expect some coherence when blending the above
+   // cases. For example we should not encounter files belonging at the
+   // time to case [Planar 0] and case [Photo D].
+   // Alas, this was only theory ! Because in practice some odd (read ill
+   // formated Dicom) files (e.g. gdcmData/US-PAL-8-10x-echo.dcm) we encounter:
+   //     - "Planar Configuration" = 0,
+   //     - "Photometric Interpretation" = "PALETTE COLOR".
+   // Hence gdcm will use the folowing "heuristic" in order to be tolerant
+   // towards Dicom-non-conformant files:
+   //   << whatever the "Planar Configuration" value might be, a
+   //      "Photometric Interpretation" set to "PALETTE COLOR" forces
+   //      a LUT intervention >>
+   //
+   // Now we are left with the following handling of the cases:
+   // - [Planar 0] OR  [Photo A] no color decoding (since respectively
+   //       Pixels are already RGB and monochrome pictures have no color :),
+   // - [Planar 1] AND [Photo B] handled with ConvertRGBPlanesToRGBPixels()
+   // - [Planar 1] AND [Photo C] handled with ConvertYcBcRPlanesToRGBPixels()
+   // - [Planar 2] OR  [Photo D] requires LUT intervention.
+
+   gdcmDebugMacro("--> ConvertHandleColor "
+                     << "Planar Configuration " << PlanarConfiguration );
+
+   if ( ! IsRawRGB() )
+   {
+      // [Planar 2] OR  [Photo D]: LUT intervention done outside
+      gdcmDebugMacro("--> RawRGB : LUT intervention done outside");
+      return;
+   }
+                                                                                
+   if ( PlanarConfiguration == 1 )
+   {
+      if ( IsYBRFull )
+      {
+         // [Planar 1] AND [Photo C] (remember YBR_FULL_422 acts as RGB)
+         gdcmDebugMacro("--> YBRFull");
+         ConvertYcBcRPlanesToRGBPixels();
+      }
+      else
+      {
+         // [Planar 1] AND [Photo C]
+         gdcmDebugMacro("--> YBRFull");
+         ConvertRGBPlanesToRGBPixels();
+      }
+      return;
+   }
+                                                                                
+   // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
+   // pixels need to be RGB-fyied anyway
+
+   if (IsRLELossless)
+   { 
+     gdcmDebugMacro("--> RLE Lossless");
+     ConvertRGBPlanesToRGBPixels();
+   }
+
+   // In *normal *case, when planarConf is 0, pixels are already in RGB
+}
+
+/// Computes the Pixels Size
+void PixelReadConvert::ComputeRawAndRGBSizes()
+{
+   int bitsAllocated = BitsAllocated;
+   // Number of "Bits Allocated" is fixed to 16 when it's 12, since
+   // in this case we will expand the image to 16 bits (see
+   //    \ref ReadAndDecompress12BitsTo16Bits() )
+   if (  BitsAllocated == 12 )
+   {
+      bitsAllocated = 16;
+   }
+                                                                                
+   RawSize =  XSize * YSize * ZSize
+                     * ( bitsAllocated / 8 )
+                     * SamplesPerPixel;
+   if ( HasLUT )
+   {
+      RGBSize = 3 * RawSize; // works for 8 and 16 bits per Pixel
+   }
+   else
+   {
+      RGBSize = RawSize;
+   }
+}
+
+/// Allocates room for RGB Pixels
+void PixelReadConvert::AllocateRGB()
+{
+  if ( RGB )
+     delete [] RGB;
+  RGB = new uint8_t[RGBSize];
+}
+
+/// Allocates room for RAW Pixels
+void PixelReadConvert::AllocateRaw()
+{
+  if ( Raw )
+     delete [] Raw;
+  Raw = new uint8_t[RawSize];
+}
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief        Print self.
+ * @param indent Indentation string to be prepended during printing.
+ * @param os     Stream to print to.
+ */
+void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
+{
+   os << indent
+      << "--- Pixel information -------------------------"
+      << std::endl;
+   os << indent
+      << "Pixel Data: offset " << PixelOffset
+      << " x(" << std::hex << PixelOffset << std::dec
+      << ")   length " << PixelDataLength
+      << " x(" << std::hex << PixelDataLength << std::dec
+      << ")" << std::endl;
+
+   if ( IsRLELossless )
+   {
+      if ( RLEInfo )
+      {
+         RLEInfo->Print( os, indent );
+      }
+      else
+      {
+         gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
+      }
+   }
+
+   if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
+   {
+      if ( JPEGInfo )
+      {
+         JPEGInfo->Print( os, indent );
+      }
+      else
+      {
+         gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
+      }
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
+
+// Note to developpers :
+// Here is a very detailled post from David Clunie, on the troubles caused 
+// 'non standard' LUT and LUT description
+// We shall have to take it into accound in our code.
+// Some day ...
+
+
+/*
+Subject: Problem with VOI LUTs in Agfa and Fuji CR and GE DX images, was Re: VOI LUT issues
+Date: Sun, 06 Feb 2005 17:13:40 GMT
+From: David Clunie <dclunie@dclunie.com>
+Reply-To: dclunie@dclunie.com
+Newsgroups: comp.protocols.dicom
+References: <1107553502.040221.189550@o13g2000cwo.googlegroups.com>
+
+> THE LUT that comes with [my] image claims to be 16-bit, but none of the
+> values goes higher than 4095.  That being said, though, none of my
+> original pixel values goes higher than that, either.  I have read
+> elsewhere on this group that when that happens you are supposed to
+> adjust the LUT.  Can someone be more specific?  There was a thread from
+> 2002 where Marco and David were mentioning doing precisely that.
+>
+> Thanks
+>
+> -carlos rodriguez
+
+
+You have encountered the well known "we know what the standard says but
+we are going to ignore it and do what we have been doing for almost
+a decade regardless" CR vendor bug. Agfa started this, but they are not
+the only vendor doing this now; GE and Fuji may have joined the club.
+
+Sadly, one needs to look at the LUT Data, figure out what the maximum
+value actually encoded is, and find the next highest power of 2 (e.g.
+212 in this case), to figure out what the range of the data is
+supposed to be. I have assumed that if the maximum value in the LUT
+data is less than a power of 2 minus 1 (e.g. 0xebc) then the intent
+of the vendor was not to use the maximum available grayscale range
+of the display (e.g. the maximum is 0xfff in this case). An alternative
+would be to scale to the actual maximum rather than a power of two.
+
+Very irritating, and in theory not totally reliable if one really
+intended the full 16 bits and only used, say 15, but that is extremely
+unlikely since everything would be too dark, and this heuristic
+seems to work OK.
+
+There has never been anything in the standard that describes having
+to go through these convolutions. Since the only value in the
+standard that describes the bit depth of the LUT values is LUT
+Descriptor value 3 and that is (usually) always required to be
+either 8 or 16, it mystifies me how the creators' of these images
+imagine that the receiver is going to divine the range that is intended. Further, the standard is quite explicit that this 3rd
+value defines the range of LUT values, but as far as I am aware, all
+the vendors are ignoring the standard and indeed sending a third value
+of 16 in all cases.
+
+This problem is not confined to CR, and is also seen with DX products.
+
+Typically I have seen:
+
+- Agfa CR, which usually (always ?) sends LUTs, values up to 0x0fff
+- Fuji CR, which occasionally send LUTs, values up to 0x03ff
+- GE DX, for presentation, which always have LUTs, up to 0x3fff
+
+Swissray, Siemens, Philips, Canon and Kodak never seem to send VOI LUTs
+at this point (which is a whole other problem). Note that the presence
+or absence of a VOI LUT as opposed to window values may be configurable
+on the modality in some cases, and I have just looked at what I happen
+to have received from a myriad of sites over whose configuration I have
+no control. This may be why the majority of Fuji images have no VOI LUTs,
+but a few do (or it may be the Siemens system that these Fuji images went
+through that perhaps added it). I do have some test Hologic DX images that
+are not from a clinical site that do actually get this right (a value
+of 12 for the third value and a max of 0xfff).
+
+Since almost every vendor that I have encountered that encodes LUTs
+makes this mistake, perhaps it is time to amend the standard to warn
+implementor's of receivers and/or sanction this bad behavior. We have
+talked about this in the past in WG 6 but so far everyone has been
+reluctant to write into the standard such a comment. Maybe it is time
+to try again, since if one is not aware of this problem, one cannot
+effectively implement display using VOI LUTs, and there is a vast
+installed base to contend with.
+
+I did not check presentation states, in which VOI LUTs could also be
+encountered, for the prevalence of this mistake, nor did I look at the
+encoding of Modality LUT's, which are unusual. Nor did I check digital
+mammography images. I would be interested to hear from anyone who has.
+
+David
+
+PS. The following older thread in this newsgroup discusses this:
+
+"http://groups-beta.google.com/group/comp.protocols.dicom/browse_frm/t hread/6a033444802a35fc/0f0a9a1e35c1468e?q=voi+lut&_done=%2Fgroup%2Fcom p.protocols.dicom%2Fsearch%3Fgroup%3Dcomp.protocols.dicom%26q%3Dvoi+lu t%26qt_g%3D1%26searchnow%3DSearch+this+group%26&_doneTitle=Back+to+Sea rch&&d#0f0a9a1e35c1468e"
+
+PPS. From a historical perspective, the following may be of interest.
+
+In the original standard in 1993, all that was said about this was a
+reference to the corresponding such where Modality LUTs are described
+that said:
+
+"The third value specifies the number of bits for each entry in the
+LUT Data. It shall take the value 8 or 16. The LUT Data shall be stored
+in a format equivalent to 8 or 16 bits allocated and high bit equal
+1-bits allocated."
+
+Since the high bit hint was not apparently explicit enough, a very
+early CP, CP 15 (submitted by Agfa as it happens), replaced this with:
+
+"The third value conveys the range of LUT entry values. It shall take
+the value 8 or 16, corresponding with the LUT entry value range of
+256 or 65536.
+
+Note:    The third value is not required for describing the
+    LUT data and is only included for informational usage
+    and for maintaining compatibility with ACRNEMA 2.0.
+
+The LUT Data contains the LUT entry values."
+
+That is how it read in the 1996, 1998 and 1999 editions.
+
+By the 2000 edition, Supplement 33 that introduced presentation states
+extensively reworked this entire section and tried to explain this in
+different words:
+
+"The output range is from 0 to 2^n-1 where n is the third value of LUT
+Descriptor. This range is always unsigned."
+
+and also added a note to spell out what the output range meant in the
+VOI LUT section:
+
+"9. The output of the Window Center/Width or VOI LUT transformation
+is either implicitly scaled to the full range of the display device
+if there is no succeeding transformation defined, or implicitly scaled
+to the full input range of the succeeding transformation step (such as
+the Presentation LUT), if present. See C.11.6.1."
+
+It still reads this way in the 2004 edition.
+
+Note that LUTs in other applications than the general VOI LUT allow for
+values other than 8 or 16 in the third value of LUT descriptor to permit
+ranges other than 0 to 255 or 65535.
+
+In addition, the DX Image Module specializes the VOI LUT
+attributes as follows, in PS 3.3 section C.8.11.3.1.5 (added in Sup 32):
+
+"The third value specifies the number of bits for each entry in the LUT
+Data (analogous to �bits stored�). It shall be between 10-16. The LUT
+Data shall be stored in a format equivalent to 16 �bits allocated� and
+�high bit� equal to �bits stored� - 1. The third value conveys the range
+of LUT entry values. These unsigned LUT entry values shall range between
+0 and 2^n-1, where n is the third value of the LUT Descriptor."
+
+So in the case of the GE DX for presentation images, the third value of
+LUT descriptor is allowed to be and probably should be 14 rather than 16.
+
+*/
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmPixelReadConvert.h b/Utilities/ITK/Utilities/gdcm/src/gdcmPixelReadConvert.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8e8f2270eb734a3580793569a3cbf3ad2396031
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmPixelReadConvert.h
@@ -0,0 +1,171 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmPixelReadConvert.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+
+#ifndef GDCMPIXELREADCONVERT_H
+#define GDCMPIXELREADCONVERT_H
+
+#include "gdcmBase.h"
+#include "gdcmException.h"
+#include <fstream>
+
+namespace gdcm
+{
+class File;
+class RLEFramesInfo;
+class JPEGFragmentsInfo;
+
+typedef void (*VOID_FUNCTION_PUINT8_PFILE_POINTER)(uint8_t *, File *);
+
+/**
+ * \brief Utility container for gathering the various forms the pixel data
+ *        migth take during the user demanded processes.
+ * WARNING : *none* of these functions may be invoked by gdcm user
+ *           (internal use only)
+ */
+class GDCM_EXPORT PixelReadConvert : public Base
+{
+friend class FileHelper;
+
+private:
+   PixelReadConvert();
+   virtual ~PixelReadConvert();
+
+   void Print( std::ostream &os = std::cout, std::string const &indent = "" );
+
+   // Getter accessors:
+   /// \brief returns pixel area holding RGB Pixels, made from Grey level + LUT
+   uint8_t *GetRGB()           { return RGB;     }
+   /// \brief returns pixel area length -RGB Pixels, (from Grey level + LUT)-
+   size_t   GetRGBSize()       { return RGBSize; }
+   /// \brief returns pixel area holding native RGB Pixels or Grey level
+   uint8_t *GetRaw()           { return Raw;     }
+   /// \brief returns pixel area size -native RGB Pixels or Grey level-
+   size_t   GetRawSize()       { return RawSize; }
+   /// \brief returns Red Green Blue Alpha LUT
+   uint8_t *GetLutRGBA()       { return LutRGBA; }
+   /// \brief returns Lut Item Number
+   int      GetLutItemNumber() { return LutItemNumber; }
+   /// \brief returns Lut Item Size
+   int      GetLutItemSize()   { return LutItemSize;   }
+   // Predicates:
+   bool IsRawRGB();
+
+// In progress
+   void GrabInformationsFromFile( File *file );
+   bool ReadAndDecompressPixelData( std::ifstream *fp );
+   void Squeeze();
+   bool BuildRGBImage();
+   void BuildLUTRGBA();
+/// \brief Allow user to pass his own function to modify pixels 
+///        (e.g; mirror, upsidedown, ...) just after reading
+   void SetUserFunction( VOID_FUNCTION_PUINT8_PFILE_POINTER userFunc ) 
+                         { UserFunction = userFunc; }
+
+   // Use the fp:
+   void ReadAndDecompress12BitsTo16Bits( std::ifstream *fp ) 
+                                 throw ( FormatError );
+   bool ReadAndDecompressJPEGFile( std::ifstream *fp );
+
+   // In place (within Decompressed and with no fp access) decompression
+   // or convertion:
+   void ConvertSwapZone();
+   void ConvertReorderEndianity();
+   bool ConvertReArrangeBits() throw ( FormatError );
+   void ConvertFixGreyLevels();
+   void ConvertRGBPlanesToRGBPixels();
+   void ConvertYcBcRPlanesToRGBPixels();
+   void ConvertHandleColor();
+
+   void ComputeRawAndRGBSizes();
+   void AllocateRGB();
+   void AllocateRaw();
+
+// Variables
+/**
+ * \brief Pixel data represented as RGB after LUT color interpretation.
+ *        'uint8_t' is just to avoid warnings at compile time.
+ *        feel free to cast it as uint16_t if you need
+ */ 
+   uint8_t *RGB;
+   /// Size of RGB image.
+   size_t   RGBSize;
+   /// Pixel data after decompression and bit/byte rearrangement.
+   uint8_t *Raw;
+   /// Size of Decompressed image.
+   size_t   RawSize;
+   /// \brief Red/Green/Blue/Alpha LookUpTable build out of the
+   ///        Red/Green/Blue LUT descriptors (see \ref BuildLUTRGBA ).
+   uint8_t *LutRGBA;
+   int LutItemNumber;
+   int LutItemSize;
+
+   // *ALL* the following info belong to the FileHelper
+   // One should think there is an analyze error in the model !
+
+   size_t PixelOffset;
+   size_t PixelDataLength;
+   int XSize;
+   int YSize;
+   int ZSize;
+   int BitsAllocated;
+   int BitsStored;
+   int HighBitPosition;
+   int SamplesPerPixel;
+   //int PixelSize; // useless
+   bool PixelSign;
+   int SwapCode;
+
+   // cache whether this is a strange GE transfer syntax (which has   
+   // one transfer syntax for the header and another for the pixel data).
+   bool IsPrivateGETransferSyntax;
+
+   bool IsRaw;
+   bool IsJPEG2000;
+   bool IsJPEGLS;
+   bool IsJPEGLossless;
+   bool IsJPEGLossy;
+   bool IsJPEG;
+   bool IsRLELossless;
+   bool IsMPEG;
+
+   RLEFramesInfo *RLEInfo;
+   JPEGFragmentsInfo *JPEGInfo;
+
+   // For handling color stage
+   int PlanarConfiguration;
+   bool IsMonochrome;
+   bool IsMonochrome1;
+   bool IsPaletteColor;
+   bool IsYBRFull;
+   bool HasLUT;
+   // The 3 LUT descriptors may be different:
+   std::string LutRedDescriptor;
+   std::string LutGreenDescriptor;
+   std::string LutBlueDescriptor;
+   uint8_t *LutRedData;
+   uint8_t *LutGreenData;
+   uint8_t *LutBlueData;
+   
+   File *FileInternal; // must be passed to User Function
+   VOID_FUNCTION_PUINT8_PFILE_POINTER UserFunction;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmPixelWriteConvert.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmPixelWriteConvert.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..032a833c38921397456530e365bb1be5f3878dda
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmPixelWriteConvert.cxx
@@ -0,0 +1,120 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmPixelWriteConvert.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmDebug.h"
+#include "gdcmPixelWriteConvert.h"
+
+namespace gdcm
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief Constructor
+ */
+PixelWriteConvert::PixelWriteConvert() 
+{
+   ReadData     = 0;
+   ReadDataSize = 0;
+
+   UserData     = 0;
+   UserDataSize = 0;
+}
+
+/**
+ * \brief Destructor
+ */
+PixelWriteConvert::~PixelWriteConvert() 
+{
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   sets Read Data (and size)
+ * @param   data data (uint8_t is for prototyping. if your data is not uint8_t
+ *                     just cast the pointer for calling the method)
+ * @param   size data size, in bytes
+ */
+void PixelWriteConvert::SetReadData(uint8_t *data, size_t size)
+{
+   ReadData = data;
+   ReadDataSize = size;
+}
+
+/**
+ * \brief   Sets the internal pointer to the caller's inData
+ *          image representation, BUT WITHOUT COPYING THE DATA.
+ *          - 'image' Pixels are presented as C-like 2D arrays : line per line.
+ *          - 'volume'Pixels are presented as C-like 3D arrays : plane per plane 
+ * \warning Since the pixels are not copied, it is the caller's responsability
+ *          not to deallocate its data before gdcm uses them (e.g. with
+ *          the Write() method )
+ * @param   data data (uint8_t is for prototyping. if your data is not uint8_t
+ *                     just cast the pointer for calling the method)
+ * @param   size size, in bytes.
+ */
+void PixelWriteConvert::SetUserData(uint8_t *data, size_t size)
+{
+   UserData = data;
+   UserDataSize = size;
+}
+
+/**
+ * \brief   Get Data (UserData or ReadData)
+ * @return  data (uint8_t is for prototyping. if your data is 
+ *                    *not* uint8_t, just cast the returned pointer)
+ */
+uint8_t *PixelWriteConvert::GetData()
+{
+   if ( UserData )
+   {
+      return UserData;
+   }
+   else
+   {
+      return ReadData;
+   }
+}
+
+/**
+ * \brief   Get Data Size (UserData or ReadData)
+ * @return  size, in bytes.
+ */
+size_t PixelWriteConvert::GetDataSize()
+{
+   if ( UserData )
+   {
+      return UserDataSize;
+   }
+   else
+   {
+      return ReadDataSize;
+   }
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmPixelWriteConvert.h b/Utilities/ITK/Utilities/gdcm/src/gdcmPixelWriteConvert.h
new file mode 100644
index 0000000000000000000000000000000000000000..d32ddeeb4928676301ba759ee52b4821ba594089
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmPixelWriteConvert.h
@@ -0,0 +1,74 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmPixelWriteConvert.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.3 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+
+#ifndef GDCMPIXELWRITECONVERT_H
+#define GDCMPIXELWRITECONVERT_H
+
+#include "gdcmCommon.h"
+#include "gdcmBase.h"
+
+namespace gdcm
+{
+/**
+ * \brief Utility container for gathering the various forms the pixel data
+ *        migth take during the user requiered processes.
+ * \warning None of the methods may be called by end user (they have no
+ *          meaning outside the class FileHelper)
+ */
+class GDCM_EXPORT PixelWriteConvert : public Base
+{
+friend class FileHelper;
+
+private:
+   PixelWriteConvert();
+   virtual ~PixelWriteConvert();
+
+   // Set/Get of images and their size
+   void SetReadData(uint8_t *data, size_t size);
+   /// \brief returns ReadData
+   uint8_t *GetReadData() { return ReadData; }
+   /// \brief returns ReadDataSize
+   size_t   GetReadDataSize() { return ReadDataSize; }
+
+   /// \brief Set UserData
+   void SetUserData(uint8_t *data, size_t size);
+   /// \brief returns UserData
+   uint8_t *GetUserData() { return UserData; }
+   /// \brief returns UserDataSize
+   size_t   GetUserDataSize() { return UserDataSize; }
+
+   // Get the used image and its size
+   uint8_t *GetData();
+   size_t   GetDataSize();
+
+// Variables
+   /// Pixel data represented as RGB after LUT color interpretation.
+   uint8_t *ReadData;
+   /// Size of RGB image.
+   size_t   ReadDataSize;
+
+   /// User pixel data
+   uint8_t *UserData;
+   /// Size of User image.
+   size_t   UserDataSize;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFrame.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFrame.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6f1768f8b7ea9b41602206b7452045168f551650
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFrame.cxx
@@ -0,0 +1,160 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmRLEFrame.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+                                                                                
+#include "gdcmRLEFrame.h"
+#include "gdcmDebug.h"
+                                                                                
+namespace gdcm
+{
+//-------------------------------------------------------------------------
+// Constructor / Destructor
+
+//-----------------------------------------------------------------------------
+// Public
+void RLEFrame::SetOffset(unsigned int id,long offset)
+{
+   gdcmAssertMacro(id<15);
+   Offset[id] = offset;
+}
+
+long RLEFrame::GetOffset(unsigned int id)
+{
+   gdcmAssertMacro(id<15);
+   return Offset[id];
+}
+
+void RLEFrame::SetLength(unsigned int id,long length)
+{
+   gdcmAssertMacro(id<15);
+   Length[id] = length;
+}
+
+long RLEFrame::GetLength(unsigned int id)
+{
+   gdcmAssertMacro(id<15);
+   return Length[id];
+}
+
+uint8_t *RLEFrame::ReadAndDecompressRLEFrame( uint8_t *subRaw,
+                                          long rawSegmentSize,
+                                          std::ifstream *fp )
+{
+   // Loop on the fragments
+   for( unsigned int k = 1; k <= NumberOfFragments; k++ )
+   {
+      // First thing need to reset file to proper position:
+      fp->seekg(Offset[k], std::ios::beg);
+      ReadAndDecompressRLEFragment(subRaw, Length[k],
+                                   rawSegmentSize, fp);
+      subRaw += rawSegmentSize;
+   }
+
+   return subRaw;
+}
+
+/**
+ * \brief Implementation of the RLE decoding algorithm for decompressing
+ *        a RLE fragment. [refer to PS 3.5-2003, section G.3.2 p 86]
+ * @param subRaw Sub region where the decoded fragment should be placed.
+ * @param fragmentSize The length of the binary fragment as found on the disk.
+ * @param rawSegmentSize The expected length of the fragment ONCE Raw.
+ * @param fp File Pointer: on entry the position should be the one of
+ *        the fragment to be decoded.
+ */
+bool RLEFrame::ReadAndDecompressRLEFragment( uint8_t *subRaw,
+                                             long fragmentSize,
+                                             long rawSegmentSize,
+                                             std::ifstream *fp )
+{
+   int8_t count;
+   long numberOfOutputBytes = 0;
+   long numberOfReadBytes = 0;
+
+   while( numberOfOutputBytes < rawSegmentSize )
+   {
+      fp->read( (char*)&count, 1 );
+      numberOfReadBytes += 1;
+      if ( count >= 0 )
+      // Note: count <= 127 comparison is always true due to limited range
+      //       of data type int8_t [since the maximum of an exact width
+      //       signed integer of width N is 2^(N-1) - 1, which for int8_t
+      //       is 127].
+      {
+         fp->read( (char*)subRaw, count + 1);
+         numberOfReadBytes   += count + 1;
+         subRaw     += count + 1;
+         numberOfOutputBytes += count + 1;
+      }
+      else
+      {
+         if ( count <= -1 && count >= -127 )
+         {
+            int8_t newByte;
+            fp->read( (char*)&newByte, 1);
+            numberOfReadBytes += 1;
+            for( int i = 0; i < -count + 1; i++ )
+            {
+               subRaw[i] = newByte;
+            }
+            subRaw     += -count + 1;
+            numberOfOutputBytes += -count + 1;
+         }
+      }
+      // if count = 128 output nothing
+                                                                                
+      if ( numberOfReadBytes > fragmentSize )
+      {
+         gdcmWarningMacro( "Read more bytes (" << numberOfReadBytes
+                              << " ) than the segment size. (" 
+                              << fragmentSize << ")" );
+         return false;
+      }
+   }
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief        Print self.
+ * @param indent Indentation string to be prepended during printing.
+ * @param os     Stream to print to.
+ */
+void RLEFrame::Print( std::ostream &os, std::string const &indent )
+{
+   os << indent
+      << "--- fragments"
+      << std::endl;
+   for ( unsigned int i = 0; i < NumberOfFragments; i++ )
+   {
+      os << indent
+         << "   offset : " <<  Offset[i]
+         << "   length : " <<  Length[i]
+         << std::endl;
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFrame.h b/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFrame.h
new file mode 100644
index 0000000000000000000000000000000000000000..112d129a832c0b7c5857042d9fbb8cdb2dd9d82d
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFrame.h
@@ -0,0 +1,73 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmRLEFrame.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+
+#ifndef GDCMRLEFRAME_H
+#define GDCMRLEFRAME_H
+
+#include "gdcmCommon.h"
+
+#include <iostream>
+#include <fstream>
+
+namespace gdcm 
+{
+/**
+ * \brief Utility class for summerizing the informations of a SINGLE RLE
+ *        frame of an "Encapsulated RLE Compressed Image" (refer to
+ *        PS 3.5-2003 annex G).
+ *        This information is a mix of:
+ *        - the RLE Header (see PS 3.5-2003 section G5) and
+ *        - the lengths of each RLE segment [ which can be decuded from
+ *          both the above RLE Header and the itemlength of the frame).
+ *
+ *        Each instance of this class (they can be as many instances for
+ *        a given Document as they are frames and they are collected in
+ *        a \ref RLEFramesInfo ) describes :
+ *        - the total number of segments (up to 15),
+ *        - the offsets of each segment of the frame,
+ *        - the (corresponding) lengths of each segment of the frame.
+ */
+class GDCM_EXPORT RLEFrame
+{
+friend class File;
+friend class RLEFramesInfo;
+private:
+   RLEFrame() { NumberOfFragments = 0; }
+   void Print( std::ostream &os = std::cout, std::string const &indent = "" );
+
+   void SetNumberOfFragments(unsigned int number) 
+                                       { NumberOfFragments = number; }   
+   unsigned int GetNumberOfFragments() { return NumberOfFragments; }
+   void SetOffset(unsigned int id, long offset);
+   long GetOffset(unsigned int id);
+   void SetLength(unsigned int id, long length);
+   long GetLength(unsigned int id);
+
+   uint8_t *ReadAndDecompressRLEFrame( uint8_t *subRaw,long rawSegmentSize,
+                                       std::ifstream *fp );
+   bool ReadAndDecompressRLEFragment( uint8_t *subRaw, long fragmentSize,
+                                      long rawSegmentSize, std::ifstream *fp );
+
+   unsigned int NumberOfFragments;
+   long Offset[15];
+   long Length[15];
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFramesInfo.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFramesInfo.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c767c8784ea458e183f0d8cb078b441ed54e750e
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFramesInfo.cxx
@@ -0,0 +1,188 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmRLEFramesInfo.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmRLEFramesInfo.h"
+#include "gdcmDebug.h"
+#include "gdcmUtil.h"
+
+#if defined(__BORLANDC__)
+   #include <mem.h> // for memset
+#endif 
+
+namespace gdcm 
+{
+//-------------------------------------------------------------------------
+// Constructor / Destructor
+RLEFramesInfo::~RLEFramesInfo()
+{
+   for(RLEFrameList::iterator it = Frames.begin(); it != Frames.end(); ++it)
+   {
+      delete (*it);
+   }
+   Frames.clear();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+void RLEFramesInfo::AddFrame(RLEFrame *frame)
+{
+   Frames.push_back(frame);
+}
+
+RLEFrame *RLEFramesInfo::GetFirstFrame()
+{
+   ItFrames = Frames.begin();
+   if (ItFrames != Frames.end())
+      return  *ItFrames;
+   return NULL;
+}
+
+RLEFrame *RLEFramesInfo::GetNextFrame()
+{
+   gdcmAssertMacro (ItFrames != Frames.end());
+
+   ++ItFrames;
+   if (ItFrames != Frames.end())
+      return  *ItFrames;
+   return NULL;
+}
+
+/**
+ * \brief     Reads from disk the Pixel Data of 'Run Length Encoded'
+ *            Dicom encapsulated file and decompress it.
+ * @param     fp already open File Pointer
+ *            from which the pixel data should be read
+ * @param raw raw
+ * @param xSize x Size
+ * @param ySize y Size
+ * @param zSize z Size
+ * @param bitsAllocated Bits allocated
+ * @return    Boolean
+ */
+bool RLEFramesInfo::DecompressRLEFile( std::ifstream *fp , uint8_t *raw, 
+                                       int xSize, int ySize, int zSize, 
+                                       int bitsAllocated )
+{
+   uint8_t *subRaw = raw;
+   long rawSegmentSize = xSize * ySize;
+
+   // Loop on the frame[s]
+   for(RLEFrameList::iterator it = Frames.begin(); it != Frames.end(); ++it)
+   {
+      subRaw = (*it)->ReadAndDecompressRLEFrame( subRaw, rawSegmentSize, fp);
+   }
+
+   if ( bitsAllocated == 16 )
+   {
+      // Try to deal with RLE 16 Bits
+      ConvertRLE16BitsFromRLE8Bits( raw, xSize, ySize, zSize );
+   }
+
+   return true;
+}
+
+/**
+ * \brief  We assume Raw contains the decoded RLE pixels but as
+ *         8 bits per pixel. We convert those pixels to 16 bits
+ *         per pixel.
+ * @param raw raw 
+ * @param xSize x Size
+ * @param ySize y Size
+ * @param numberOfFrames number of frames 
+ * @return    Boolean always true
+ */
+bool RLEFramesInfo::ConvertRLE16BitsFromRLE8Bits(uint8_t *raw, int xSize, 
+                                                 int ySize, int numberOfFrames)
+{
+   size_t pixelNumber = xSize * ySize;
+   size_t rawSize     = pixelNumber * numberOfFrames * 2;
+
+   // We assumed Raw contains the decoded RLE pixels but as
+   // 8 bits per pixel. In order to convert those pixels to 16 bits
+   // per pixel we cannot work in place within Raw and hence
+   // we copy it in a safe place, say copyRaw.
+
+   uint8_t *copyRaw = new uint8_t[rawSize];
+   memmove( copyRaw, raw, rawSize );
+
+   uint8_t *x = raw;
+   uint8_t *a;
+   uint8_t *b;
+
+   // Warning : unckecked patch to see the behaviour on Big Endian Processors
+
+   if ( !Util::IsCurrentProcessorBigEndian() )
+   { 
+      a = copyRaw;         // beginning of 'low bytes'
+      b = a + pixelNumber; // beginning of 'hight bytes'
+   }
+   else
+   {
+      b = copyRaw;         // beginning of 'low bytes'
+      a = b + pixelNumber; // beginning of 'hight bytes'
+   } 
+
+   // Re order bytes
+   for ( int i = 0; i < numberOfFrames; i++ )
+   {
+      for ( unsigned int j = 0; j < pixelNumber; j++ )
+      {
+         *(x++) = *(b++);
+         *(x++) = *(a++);
+      }
+   }
+
+   delete[] copyRaw;
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief        Print self.
+ * @param indent Indentation string to be prepended during printing.
+ * @param os     Stream to print to.
+ */
+void RLEFramesInfo::Print( std::ostream &os, std::string indent )
+{
+   os << std::endl;
+   os << indent
+      << "----------------- RLE frames --------------------------------"
+      << std::endl;
+   os << indent
+      << "Total number of Frames : " << Frames.size()
+      << std::endl;
+   int frameNumber = 0;
+   for(RLEFrameList::iterator it = Frames.begin(); it != Frames.end(); ++it)
+   {
+      os << indent
+         << "   frame number :" << frameNumber++
+         << std::endl;
+      (*it)->Print( os, indent + "   " );
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFramesInfo.h b/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFramesInfo.h
new file mode 100644
index 0000000000000000000000000000000000000000..bc3a8f8cc81bb3944d00c8eee248ef94537abc5b
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmRLEFramesInfo.h
@@ -0,0 +1,69 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmRLEFramesInfo.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+
+#ifndef GDCMRLEFRAMESINFO_H
+#define GDCMRLEFRAMESINFO_H
+
+#include "gdcmRLEFrame.h"
+
+#include <list>
+
+namespace gdcm 
+{
+/**
+ * \brief Utility class for gathering the informations of the collection
+ *        of RLE frame[s] (see \ref RLEFrame)  when handling
+ *        "Encapsulated RLE Compressed Images" (see PS 3.5-2003 annex G). 
+ *        Note: a classical image can be considered as the degenerated case
+ *              of a multiframe image. In this case the collection is limited
+ *              to a single individual frame.
+ *        The informations on each frame are obtained during the pixel parsing
+ *        of a gdcm::File (refer to
+ *          \ref File::ComputeRLEInfo() ).
+ *        They shall be used when (if necessary) decoding the frames.
+ *
+ *        This class is simply a stl list<> of \ref RLEFrame.
+ */
+class GDCM_EXPORT RLEFramesInfo
+{
+friend class PixelReadConvert;
+friend class File;
+
+private:
+   ~RLEFramesInfo();
+   void Print( std::ostream &os = std::cout, std::string indent = "" );
+   bool DecompressRLEFile( std::ifstream *fp, uint8_t *subRaw, int xSize, 
+                           int ySize, int zSize, int bitsAllocated );
+   bool ConvertRLE16BitsFromRLE8Bits( uint8_t *subRaw, int xSize, int ySize, 
+                                      int numberOfFrames );
+
+   void AddFrame(RLEFrame *frame);
+
+   RLEFrame *GetFirstFrame();
+   RLEFrame *GetNextFrame();
+
+   typedef std::list<RLEFrame *> RLEFrameList;
+
+   RLEFrameList Frames;
+   RLEFrameList::iterator ItFrames;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmSQItem.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmSQItem.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0a8634e94cc8f083c791e808aa2ec67c61e78d9a
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmSQItem.cxx
@@ -0,0 +1,333 @@
+/*=========================================================================
+  
+  Program:   gdcm
+  Module:    $RCSfile: gdcmSQItem.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.8 $
+  
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+  
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+  
+=========================================================================*/
+
+#include "gdcmSQItem.h"
+#include "gdcmSeqEntry.h"
+#include "gdcmValEntry.h"
+#include "gdcmBinEntry.h"
+#include "gdcmGlobal.h"
+#include "gdcmDictSet.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+
+#include <fstream>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor from a given SQItem
+ */
+SQItem::SQItem(int depthLevel ) 
+          : DocEntrySet( )
+{
+   SQDepthLevel = depthLevel;
+   SQItemNumber = 0;
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+SQItem::~SQItem() 
+{
+   ClearEntry();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/*
+ * \brief   canonical Writer
+ * @param fp     file pointer to an already open file. 
+ * @param filetype type of the file (ACR, ImplicitVR, ExplicitVR, ...)
+ */
+void SQItem::WriteContent(std::ofstream *fp, FileType filetype)
+{
+   int j;
+   uint16_t item[4] = { 0xfffe, 0xe000, 0xffff, 0xffff };
+   uint16_t itemt[4]= { 0xfffe, 0xe00d, 0x0000, 0x0000 };
+
+    //we force the writting of an 'Item' Start Element
+    // because we want to write the Item as a 'No Length' item
+   for(j=0;j<4;++j)
+   {
+      binary_write( *fp, item[j]);  // fffe e000 ffff ffff 
+   }
+     
+   for (ListDocEntry::iterator it = DocEntries.begin();  
+                               it != DocEntries.end();
+                             ++it)
+   {   
+      // we skip delimitors (start and end one) because 
+      // we force them as 'no length'
+      if ( (*it)->GetGroup() == 0xfffe )
+      {
+         continue;
+      }
+
+      // Fix in order to make some MR PHILIPS images e-film readable
+      // see gdcmData/gdcm-MR-PHILIPS-16-Multi-Seq.dcm:
+      // we just *always* ignore spurious fffe|0000 tag ! 
+      if ( (*it)->GetGroup() == 0xfffe && (*it)->GetElement() == 0x0000 )
+      {
+          break; // FIXME : break or continue; ?!?  
+                 // --> makes no difference since the only bugged file we have
+                 // contains 'impossible tag' fffe|0000 in last position !                            
+      }
+
+      (*it)->WriteContent(fp, filetype);
+   }
+      
+    //we force the writting of an 'Item Delimitation' item
+    // because we wrote the Item as a 'no Length' item
+   for(j=0;j<4;++j)
+   {
+      binary_write( *fp, itemt[j]);  // fffe e000 0000 0000
+   } 
+}
+
+/**
+ * \brief   Compute the full length of the SQItem (not only value length)
+ *           depending on the VR.
+ */
+uint32_t SQItem::ComputeFullLength()
+{
+   uint32_t l = 8;  // Item Starter length
+   for (ListDocEntry::iterator it = DocEntries.begin();  
+                               it != DocEntries.end();
+                             ++it)
+   {   
+      // we skip delimitors (start and end one) because 
+      // we force them as 'no length'
+      if ( (*it)->GetGroup() == 0xfffe )
+      {
+         continue;
+      }
+      l += (*it)->ComputeFullLength();
+   }
+   l += 8; // 'Item Delimitation' item 
+   return l;  
+}
+
+/**
+ * \brief   Inserts *in the right place* any Entry (Dicom Element)
+ *          into the Sequence Item
+ * @param entry Entry to add
+ * @return always true 
+ */
+bool SQItem::AddEntry(DocEntry *entry)
+{   
+   if (DocEntries.empty() )
+   {
+      DocEntries.push_back(entry);
+      return true;
+   }
+ 
+   ListDocEntry::iterator insertSpot;
+   ListDocEntry::iterator it = DocEntries.end();
+   do
+   {
+      it--;
+
+      if ( (*it)->IsItemDelimitor() )
+      {
+         continue;
+      }
+      if ( (*it)->GetGroup() < entry->GetGroup() )
+         break;
+      else
+         if ( (*it)->GetGroup() == entry->GetGroup() &&
+              (*it)->GetElement() < entry->GetElement() )
+            break;
+   } while (it != DocEntries.begin() );
+  
+   insertSpot = it++;
+   insertSpot++; // ?!?
+   DocEntries.insert(insertSpot, entry); 
+   return true;
+}   
+
+/**
+ * \brief   Clear the std::list from given entry AND delete the entry.
+ * @param   entryToRemove Entry to remove AND delete.
+ * @return true if the entry was found and removed; false otherwise
+ */
+bool SQItem::RemoveEntry( DocEntry *entryToRemove )
+{
+   for(ListDocEntry::iterator it = DocEntries.begin();
+                              it != DocEntries.end();
+                            ++it)
+   {
+      if ( *it == entryToRemove )
+      {
+         DocEntries.erase(it);
+         gdcmWarningMacro( "One element erased: " << entryToRemove->GetKey() );
+         delete entryToRemove;
+         return true;
+      }
+   }
+   gdcmWarningMacro( "Entry not found: " << entryToRemove->GetKey() );
+   return false ;
+}
+
+/**
+ * \brief   Clear the std::list from given entry BUT keep the entry.
+ * @param   entryToRemove Entry to remove.
+ * @return true if the entry was found and removed; false otherwise
+ */
+bool SQItem::RemoveEntryNoDestroy(DocEntry *entryToRemove)
+{
+   for(ListDocEntry::iterator it =  DocEntries.begin();
+                              it != DocEntries.end();
+                            ++it)
+   {
+      if ( *it == entryToRemove )
+      {
+         DocEntries.erase(it);
+         gdcmWarningMacro( "One element removed, no destroyed: "
+                            << entryToRemove->GetKey() );
+         return true;
+      }
+   }
+                                                                                
+   gdcmWarningMacro( "Entry not found:" << entryToRemove->GetKey() );
+   return false ;
+}
+                                                                                
+/**
+ * \brief  Remove all entry in the Sequence Item 
+ */
+void SQItem::ClearEntry()
+{
+   for(ListDocEntry::iterator cc = DocEntries.begin();
+                              cc != DocEntries.end();
+                            ++cc)
+   {
+      delete *cc;
+   }
+   DocEntries.clear();
+}
+
+/**
+ * \brief  Clear the std::list from given Sequence Item  BUT keep the entries
+ */
+void SQItem::ClearEntryNoDestroy()
+{
+   DocEntries.clear();
+}
+
+
+/**
+ * \brief  Move all the entries from a given Sequence Item 
+ */
+void SQItem::MoveObject(SQItem *source)
+{
+   DocEntries = source->DocEntries;
+   source->ClearEntryNoDestroy();
+}
+
+/**
+ * \brief   Get the first Dicom entry while visiting the SQItem
+ * \return  The first DocEntry if found, otherwhise 0
+ */
+DocEntry *SQItem::GetFirstEntry()
+{
+   ItDocEntries = DocEntries.begin();
+   if ( ItDocEntries != DocEntries.end() )
+      return *ItDocEntries;
+   return 0;   
+}
+                                                                                
+/**
+ * \brief   Get the next Dicom entry while visiting the SQItem
+ * \return  The next DocEntry if found, otherwhise NULL
+ */
+DocEntry *SQItem::GetNextEntry()
+{
+   ++ItDocEntries;
+   if ( ItDocEntries != DocEntries.end() )
+      return  *ItDocEntries;
+   return NULL;
+}
+
+/**
+ * \brief   Gets a Dicom Element inside a SQ Item Entry
+ * @param   group   Group number of the Entry
+ * @param   elem  Element number of the Entry
+ * @return Entry whose (group,elem) was passed. 0 if not found
+ */
+DocEntry *SQItem::GetDocEntry(uint16_t group, uint16_t elem)
+{
+   for(ListDocEntry::iterator i =  DocEntries.begin();
+                              i != DocEntries.end(); 
+                            ++i)
+   {
+      if ( (*i)->GetGroup() == group && (*i)->GetElement() == elem )
+         return *i;
+   }
+   return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/*
+ * \brief   canonical Printer
+ * @param os     Stream to print to. 
+ * @param indent Indentation string to be prepended during printing.
+ */
+void SQItem::Print(std::ostream &os, std::string const &)
+{
+   itksys_ios::ostringstream s;
+
+   if (SQDepthLevel > 0)
+   {
+      for (int i = 0; i < SQDepthLevel; ++i)
+      {
+         s << "   | " ;
+      }
+   }
+   os << s.str() << " --- SQItem number " << SQItemNumber  << std::endl;
+   for (ListDocEntry::iterator i  = DocEntries.begin();
+                               i != DocEntries.end();
+                             ++i)
+   {
+      DocEntry *Entry = *i;
+      bool PrintEndLine = true;
+
+      os << s.str();
+      Entry->SetPrintLevel(PrintLevel);
+      Entry->Print(os); 
+      if ( dynamic_cast<SeqEntry*>(Entry) )
+      {
+         PrintEndLine = false;
+      }
+      if (PrintEndLine)
+      {
+         os << std::endl;
+      }
+   } 
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmSQItem.h b/Utilities/ITK/Utilities/gdcm/src/gdcmSQItem.h
new file mode 100644
index 0000000000000000000000000000000000000000..ad1b315ad3e4a3640147e29a1ed9173698690eb1
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmSQItem.h
@@ -0,0 +1,98 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmSQItem.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.5 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+#ifndef GDCMSQITEM_H
+#define GDCMSQITEM_H
+
+#include "gdcmDocEntrySet.h"
+#include "gdcmElementSet.h"
+
+#include <list>
+#include <fstream>
+
+namespace gdcm 
+{
+class DocEntry;
+
+//-----------------------------------------------------------------------------
+typedef std::list<DocEntry *> ListDocEntry;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief a SeqEntry is composed by a set of SQItems.
+ *        Each SQItem is composed by a set of DocEntry
+ *        A DocEntry may be a SeqEntry
+ *        ... and so forth 
+ */ 
+class GDCM_EXPORT SQItem : public DocEntrySet 
+{
+public:
+   SQItem(int depthLevel);
+   ~SQItem();
+
+   virtual void Print(std::ostream &os = std::cout, std::string const &indent = "" ); 
+   void WriteContent(std::ofstream *fp, FileType filetype);
+   uint32_t ComputeFullLength();
+
+   bool AddEntry(DocEntry *Entry); // add to the List
+   bool RemoveEntry(DocEntry *EntryToRemove);
+   bool RemoveEntryNoDestroy(DocEntry *EntryToRemove);
+   void ClearEntry();
+   void ClearEntryNoDestroy();
+   void MoveObject(SQItem *source);
+  
+   DocEntry *GetFirstEntry();
+   DocEntry *GetNextEntry();
+
+   DocEntry *GetDocEntry(uint16_t group, uint16_t elem);
+
+   bool IsEmpty() { return DocEntries.empty(); }
+
+   /// \brief   returns the ordinal position of a given SQItem
+   int GetSQItemNumber() { return SQItemNumber; }
+   /// \brief   Sets the ordinal position of a given SQItem
+   void SetSQItemNumber(int itemNumber) { SQItemNumber = itemNumber; }
+
+   ///  \brief Accessor on \ref SQDepthLevel.
+   int GetDepthLevel() { return SQDepthLevel; }                                                                             
+
+   ///  \brief Accessor on \ref SQDepthLevel.
+   void SetDepthLevel(int depth) { SQDepthLevel = depth; }
+
+protected:
+// Variables that need to be accessed in subclasses
+   /// \brief Chained list of Doc Entries
+   ListDocEntry DocEntries;
+   /// Iterator, used to visit the entries
+   ListDocEntry::iterator ItDocEntries;
+   /// Iterator, used to visit the Val Entries (for Python users)
+   ListDocEntry::iterator ItValEntries;
+  
+private:
+   /// \brief Sequences can be nested. This \ref SQDepthLevel represents
+   ///        the level of the nesting of instances of this class.
+   ///        \ref SQDepthLevel and its \ref SeqEntry::SQDepthLevel
+   ///        counterpart are only defined on printing purposes
+   ///        (see \ref Print).
+   int SQDepthLevel;
+
+   /// \brief SQ Item ordinal number 
+   int SQItemNumber;
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmSeqEntry.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmSeqEntry.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d0404440ae372fb417cd5714f784a38bfa120af0
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmSeqEntry.cxx
@@ -0,0 +1,269 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmSeqEntry.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmSeqEntry.h"
+#include "gdcmSQItem.h"
+#include "gdcmValEntry.h"
+#include "gdcmTS.h"
+#include "gdcmGlobal.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor from a given SeqEntry
+ */
+SeqEntry::SeqEntry( DictEntry *e ) 
+             : DocEntry(e)
+{
+   Length       = 0;
+   ReadLength   = 0xffffffff;
+   SQDepthLevel = -1;
+
+   DelimitorMode = false;
+   SeqTerm  = NULL;
+}
+
+/**
+ * \brief   Constructor from a given DocEntry
+ * @param   e Pointer to existing Doc entry
+ * @param   depth depth level of the current Seq entry
+ */
+SeqEntry::SeqEntry( DocEntry *e, int depth )
+             : DocEntry( e->GetDictEntry() )
+{
+   Length       = 0;
+   ReadLength   = 0xffffffff;
+   SQDepthLevel = depth;
+
+   ImplicitVR   = e->IsImplicitVR();
+   Offset       = e->GetOffset();
+   SeqTerm = NULL;
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+SeqEntry::~SeqEntry()
+{
+   ClearSQItem();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/*
+ * \brief   canonical Writer
+ * @param fp pointer to an already open file
+ * @param filetype type of the file (ACR, ImplicitVR, ExplicitVR, ...)
+ */
+void SeqEntry::WriteContent(std::ofstream *fp, FileType filetype)
+{
+   uint16_t seq_term_gr = 0xfffe;
+   uint16_t seq_term_el = 0xe0dd;
+   uint32_t seq_term_lg = 0x00000000;
+ 
+   // ignore 'Zero length' Sequences
+   if ( GetReadLength() == 0 )
+      return;
+
+   DocEntry::WriteContent(fp, filetype);
+   for(ListSQItem::iterator cc  = Items.begin();
+                            cc != Items.end();
+                          ++cc)
+   {        
+      (*cc)->WriteContent(fp, filetype);
+   }
+   
+   // we force the writting of a Sequence Delimitation item
+   // because we wrote the Sequence as a 'no Length' sequence
+   binary_write(*fp, seq_term_gr);
+   binary_write(*fp, seq_term_el);
+   binary_write(*fp, seq_term_lg);
+}
+
+/**
+ * \brief   Compute the full length of the SeqEntry (not only value
+ *          length) depending on the VR.
+ */
+uint32_t SeqEntry::ComputeFullLength()
+{
+   uint32_t l = 12; // Tag (4) + VR (explicit) 4 + 4 (length);   
+   for(ListSQItem::iterator cc  = Items.begin();
+                            cc != Items.end();
+                          ++cc)
+   {        
+      l += (*cc)->ComputeFullLength();
+   }   
+   l += 8; // seq_term Tag (4) +  seq_term_lg (4)
+   return l;
+}
+
+/**
+ * \brief   adds the passed ITEM to the ITEM chained List for this SeQuence.
+ * @param sqItem SQItem to be pushed back in the SeqEntry
+ * @param itemNumber ordinal number of the SQItem
+ *  \note NOT end-user intendend method !
+ */
+void SeqEntry::AddSQItem(SQItem *sqItem, int itemNumber)
+{
+// FIXME : SQItemNumber is supposed to be the ordinal number of the SQItem
+//         within the Sequence.
+//         Either only 'push_back' is allowed, 
+//                and we just have to do something like SeqEntry::lastNb++
+//         Or we can add (or remove) anywhere, and SQItemNumber will be broken
+   sqItem->SetSQItemNumber(itemNumber);
+   Items.push_back(sqItem);
+}
+
+/**
+ * \brief Remove all SQItem.
+ */
+void SeqEntry::ClearSQItem()
+{
+   for(ListSQItem::iterator cc = Items.begin(); cc != Items.end(); ++cc)
+   {
+      delete *cc;
+   }
+   if (SeqTerm)
+   {
+      delete SeqTerm;
+   }
+}
+
+/**
+ * \brief   Get the first entry while visiting the SeqEntry
+ * \return  The first SQItem if found, otherwhise NULL
+ */ 
+SQItem *SeqEntry::GetFirstSQItem()
+{
+   ItSQItem = Items.begin();
+   if (ItSQItem != Items.end())
+      return *ItSQItem;
+   return NULL;
+} 
+
+/**
+ * \brief   Get the next SQItem while visiting the SeqEntry
+ * \note : meaningfull only if GetFirstEntry already called
+ * \return  The next SQItem if found, otherwhise NULL
+ */
+
+SQItem *SeqEntry::GetNextSQItem()
+{
+   gdcmAssertMacro (ItSQItem != Items.end())
+   {
+      ++ItSQItem;
+      if (ItSQItem != Items.end())
+         return *ItSQItem;
+   }
+   return NULL;
+}
+ 
+/**
+ * \brief return a pointer to the SQItem referenced by its ordinal number.
+ *        Returns the first item when argument is negative.
+ *        Returns the  last item when argument is bigger than the total
+ *        item number.
+ */
+SQItem *SeqEntry::GetSQItem(int nb)
+{
+   if (nb<0)
+   {
+      return *(Items.begin());
+   }
+   int count = 0 ;
+   for(ListSQItem::iterator cc = Items.begin();
+                           cc != Items.end();
+                           count ++, ++cc)
+   {
+      if (count == nb)
+      {
+         return *cc;
+      }
+   }
+   return *(Items.end());
+}
+
+/**
+ * \brief returns the number of SQItems within the current Sequence
+ */
+unsigned int SeqEntry::GetNumberOfSQItems()
+{
+   return Items.size();
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   canonical Printer
+ */
+void SeqEntry::Print( std::ostream &os, std::string const & )
+{
+   // First, Print the Dicom Element itself.
+   os << "S ";
+   DocEntry::Print(os);
+   os << std::endl;
+
+   if (GetReadLength() == 0)
+      return;
+
+   // Then, Print each SQ Item   
+   for(ListSQItem::iterator cc = Items.begin(); cc != Items.end(); ++cc)
+   {
+      (*cc)->SetPrintLevel(PrintLevel);
+      (*cc)->Print(os);   
+   }
+
+   // at end, print the sequence terminator item, if any
+   if (DelimitorMode)
+   {
+      int i;
+      for ( i = 0; i < SQDepthLevel; i++ )
+         os << "   | " ;
+      os << " --- "  << std::endl;
+      for ( i = 0; i < SQDepthLevel; i++ )
+         os << "   | " ;
+      if (SeqTerm != NULL)
+      {
+         SeqTerm->SetPrintLevel(PrintLevel);
+         SeqTerm->Print(os);
+         os << std::endl;
+      } 
+      else 
+      {
+         // fuse
+         gdcmWarningMacro("  -------- should have a sequence terminator item");
+      }
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmSeqEntry.h b/Utilities/ITK/Utilities/gdcm/src/gdcmSeqEntry.h
new file mode 100644
index 0000000000000000000000000000000000000000..95e1df3c28f4fe54ea6a092b0f863200e5d61c06
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmSeqEntry.h
@@ -0,0 +1,95 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmSeqEntry.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMSQDOCENTRY_H
+#define GDCMSQDOCENTRY_H
+
+#include "gdcmDocEntry.h"
+
+#include <list>
+
+namespace gdcm 
+{
+class SQItem;
+//-----------------------------------------------------------------------------
+typedef std::list<SQItem *> ListSQItem;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief a SeqEntry (as opposed to a ValEntry) is a non elementary DocEntry.
+ *        It is composed by a set of SQItems.
+ *        Each SQItem is composed by a set of DocEntry
+ *        A DocEntry may be a SeqEntry
+ *        ... and so forth 
+ */ 
+class GDCM_EXPORT SeqEntry : public DocEntry 
+{
+public:
+   SeqEntry( DictEntry *e);
+   SeqEntry( DocEntry *d, int depth );
+   ~SeqEntry();
+   
+   void Print(std::ostream &os = std::cout, std::string const &indent = "" ); 
+   void WriteContent(std::ofstream *fp, FileType filetype);
+   uint32_t ComputeFullLength();
+
+   void AddSQItem(SQItem *it, int itemNumber);
+   void ClearSQItem();
+   SQItem *GetFirstSQItem();
+   SQItem *GetNextSQItem();
+   SQItem *GetSQItem(int itemNumber);
+   unsigned int GetNumberOfSQItems();
+      
+   /// Sets the delimitor mode
+   void SetDelimitorMode(bool dm) { DelimitorMode = dm; }
+   /// Sets the Sequence Delimitation Item
+   void SetDelimitationItem(DocEntry *e) { SeqTerm = e;   }
+
+   /// Gets the Sequence Delimitation Item
+   DocEntry *GetDelimitationItem() { return SeqTerm;}
+
+   /// Gets the depth level
+   int GetDepthLevel() const { return SQDepthLevel; }
+   /// Sets the depth level of a Sequence Entry embedded in a SeQuence
+   void SetDepthLevel(int depth) { SQDepthLevel = depth; }
+
+protected:
+
+private:
+// Variables
+   /// If this Sequence is in delimitor mode (length =0xffffffff) or not
+   bool DelimitorMode;
+   
+   /// Chained list of SQ Items
+   ListSQItem Items;
+   /// iterator on the SQItems of the current SeqEntry
+   ListSQItem::iterator ItSQItem;
+
+   /// sequence terminator item 
+   DocEntry *SeqTerm;
+
+   /// \brief Defines the depth level of this \ref SeqEntry inside
+   ///        the (optionaly) nested sequences. \ref SQDepthLevel
+   ///        and its \ref SQItem::SQDepthLevel counterpart
+   ///        are only defined on printing purposes (see \ref Print).
+   int SQDepthLevel;
+};
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmSerieHelper.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmSerieHelper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..bf9d89ea2e45583c86846a28c294a8cd74f2dfd9
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmSerieHelper.cxx
@@ -0,0 +1,948 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmSerieHelper.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 18:29:58 $
+  Version:   $Revision: 1.21 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmSerieHelper.h"
+#include "gdcmDirList.h"
+#include "gdcmFile.h"
+#include "gdcmDictEntry.h" // for TranslateToKey
+#include "gdcmDebug.h"
+#include "gdcmUtil.h"
+
+#include <math.h>
+#include <vector>
+#include <algorithm>
+#include <map>
+#include <stdio.h>  //for sscanf
+
+namespace gdcm
+{
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor from a given SerieHelper
+ */
+SerieHelper::SerieHelper()
+{
+   m_UseSeriesDetails = false;
+   ClearAll();
+   UserLessThanFunction = 0;
+   DirectOrder = true;
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+SerieHelper::~SerieHelper()
+{
+   ClearAll();
+}
+
+/**
+ * \brief  Preventively, clear everything at constructor time.
+ *         ( use it at destructor time.)
+ */
+void SerieHelper::ClearAll()
+{
+   // For all the 'Single SerieUID' Filesets that may already exist 
+   FileList *l = GetFirstSingleSerieUIDFileSet();
+   while (l)
+   { 
+      // For all the gdcm::File of a File set
+      for (gdcm::FileList::iterator it  = l->begin();
+                                    it != l->end(); 
+                                  ++it)
+      {
+         delete *it; // remove each entry
+      }
+      l->clear();
+      delete l;     // remove the container
+      l = GetNextSingleSerieUIDFileSet();
+   }
+   // Need to clear that too:
+   SingleSerieUIDFileSetHT.clear();
+}
+
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+
+// Public
+/**
+ * \brief add a gdcm::File to the Fileset corresponding to its Serie UID
+ * @param   filename Name of the file to deal with
+ */
+void SerieHelper::AddFileName(std::string const &filename)
+{
+   // Create a DICOM file
+   File *header = new File ();
+   header->SetLoadMode(LoadMode);
+   header->SetFileName( filename ); 
+   header->Load();
+
+   if ( header->IsReadable() )
+   {
+      if ( !AddFile( header ) )
+      {
+         // at least one rule was unmatched we need to deallocate the file:
+         delete header;
+      }
+   }
+   else
+   {
+      gdcmWarningMacro("Could not read file: " << filename );
+      delete header;
+   }
+}
+
+/**
+ * \brief add a gdcm::File to the first (and supposed to be unique) file set
+ *        of the gdcm::SerieHelper.
+ * \warning : this method should be used by aware users only!
+ *           Passing a gdcm::File* has the same effect than passing a file name!
+ * \todo : decide which one is wrong (the method, or the commentary)!
+ *           the following comment doesn't match the method :-(
+ *            User is supposed to know the files he want to deal with
+ *           and consider them they belong to the same Serie
+ *           (even if their Serie UID is different)
+ *           user will probabely OrderFileList() this list (actually, ordering
+ *           user choosen gdm::File is the sole interest of this method)
+ *           Moreover, using vtkGdcmReader::SetCoherentFileList() will avoid
+ *           vtkGdcmReader parsing twice the same files. 
+ *           *no* coherence check is performed, but those specified
+ *           by SerieHelper::AddRestriction()
+ * @param   header gdcm::File* of the file to deal with
+ * @return  true if file was added, false if file was rejected
+ */
+bool SerieHelper::AddFile(File *header)
+{
+   int allrules = 1;
+   // First step the user has defined a set of rules for the DICOM 
+   // he is looking for.
+   // make sure the file correspond to his set of rules:
+
+   std::string s;
+   for(SerieExRestrictions::iterator it2 = ExRestrictions.begin();
+     it2 != ExRestrictions.end();
+     ++it2)
+   {
+      const ExRule &r = *it2;
+      s = header->GetEntryValue( r.group, r.elem );
+      if ( !Util::CompareDicomString(s, r.value.c_str(), r.op) )
+      {
+         // Argh ! This rule is unmatched; let's just quit
+         allrules = 0;
+         break;
+      }
+   }
+
+   if ( allrules ) // all rules are respected:
+   {
+      // Allright! we have a found a DICOM that matches the user expectation. 
+      // Let's add it to the specific 'id' which by default is uid (Serie UID)
+      // but can be `refined` by user with more paramater (see AddRestriction(g,e))
+ 
+      std::string id = CreateUniqueSeriesIdentifier( header );
+      // if id == GDCM_UNFOUND then consistently we should find GDCM_UNFOUND
+      // no need here to do anything special
+ 
+      if ( SingleSerieUIDFileSetHT.count(id) == 0 )
+      {
+         gdcmDebugMacro(" New Serie UID :[" << id << "]");
+         // create a std::list in 'id' position
+         SingleSerieUIDFileSetHT[id] = new FileList;
+      }
+      // Current Serie UID and DICOM header seems to match add the file:
+      SingleSerieUIDFileSetHT[id]->push_back( header );
+   }
+   else
+   {
+      // one rule not matched, tell user:
+      return false;
+   }
+   return true;
+}
+
+/**
+ * \brief add a rule for restricting a DICOM file to be in the serie we are
+ * trying to find. For example you can select only the DICOM files from a
+ * directory which would have a particular EchoTime==4.0.
+ * This method is a user level, value is not required to be formatted as a DICOM
+ * string
+ * \todo find a trick to allow user to say if he wants the Rectrictions 
+ *       to be *ored* (and not only *anded*)
+ * @param   group  Group number of the target tag.
+ * @param   elem Element number of the target tag.
+ * @param value value to be checked to exclude File
+ * @param op  operator we want to use to check
+ */
+void SerieHelper::AddRestriction(uint16_t group, uint16_t elem, 
+                                 std::string const &value, int op)
+{
+   ExRule r;
+   r.group = group;
+   r.elem  = elem;
+   r.value = value;
+   r.op    = op;
+   ExRestrictions.push_back( r ); 
+}
+
+void SerieHelper::AddRestriction(uint16_t group, uint16_t elem)
+{
+  ExRule r;
+  r.group = group;
+  r.elem  = elem;
+  ExRefine.push_back( r );
+}
+
+#ifndef GDCM_LEGACY_REMOVE
+/**
+ * \brief add a rule for restricting a DICOM file to be in the serie we are
+ * trying to find. For example you can select only the DICOM files from a
+ * directory which would have a particular EchoTime==4.0.
+ * This method is a user level, value is not required to be formatted as a DICOM
+ * string
+ * @param   group  Group number of the target tag.
+ * @param   elem Element number of the target tag.
+ * @param value value to be checked to exclude File 
+ * @deprecated use : AddRestriction(uint16_t group, uint16_t elem, 
+ *                                 std::string const &value, int op);
+ */
+void SerieHelper::AddRestriction(TagKey const &key, std::string const &value)
+{
+   Rule r;
+   r.first = key;
+   r.second = value;
+   Restrictions.push_back( r ); 
+}
+#endif
+
+/**
+ * \brief Sets the root Directory
+ * @param   dir Name of the directory to deal with
+ * @param recursive whether we want explore recursively the root Directory
+ */
+void SerieHelper::SetDirectory(std::string const &dir, bool recursive)
+{
+   DirList dirList(dir, recursive); // OS specific
+  
+   DirListType filenames_list = dirList.GetFilenames();
+   for( DirListType::const_iterator it = filenames_list.begin(); 
+        it != filenames_list.end(); ++it)
+   {
+      AddFileName( *it );
+   }
+}
+
+/**
+ * \brief Sorts the given Fileset
+ * \warning This could be implemented in a 'Strategy Pattern' approach
+ *          But as I don't know how to do it, I leave it this way
+ *          BTW, this is also a Strategy, I don't know this is 
+ *          the best approach :)
+ */
+void SerieHelper::OrderFileList(FileList *fileSet)
+{
+
+   if ( SerieHelper::UserLessThanFunction )
+   {
+      UserOrdering( fileSet );
+      return; 
+   }
+   else if ( ImagePositionPatientOrdering( fileSet ) )
+   {
+      return ;
+   }
+   else if ( ImageNumberOrdering(fileSet ) )
+   {
+      return ;
+   }
+   else  
+   {
+      FileNameOrdering(fileSet );
+   }
+}
+
+/**
+ * \brief Elementary coherence checking of the files with the same Serie UID
+ * Only sizes and pixel type are checked right now ...
+ */ 
+bool SerieHelper::IsCoherent(FileList *fileSet)
+{
+   if(fileSet->size() == 1)
+   return true;
+
+   FileList::const_iterator it = fileSet->begin();
+
+   int nX =               (*it)->GetXSize();
+   int nY =               (*it)->GetYSize();
+   int pixelSize =        (*it)->GetPixelSize();
+   bool signedPixelData = (*it)->IsSignedPixelData();
+   it ++;
+   for ( ;
+         it != fileSet->end();
+       ++it)
+   {
+      if ( (*it)->GetXSize() != nX )
+         return false;
+      if ( (*it)->GetYSize() != nY )
+         return false;
+      if ( (*it)->GetPixelSize() != pixelSize )
+         return false;
+      if ( (*it)->IsSignedPixelData() != signedPixelData )
+         return false;
+      // probabely more is to be checked (?)
+   }
+   return true;
+}
+
+#ifndef GDCM_LEGACY_REMOVE
+/**
+ * \brief   accessor (DEPRECATED :  use GetFirstSingleSerieUIDFileSet )
+ *          Warning : 'coherent' means here they have the same Serie UID
+ * @return  The first FileList if found, otherwhise NULL
+ */
+FileList *SerieHelper::GetFirstCoherentFileList()
+{
+   ItFileSetHt = SingleSerieUIDFileSetHT.begin();
+   if ( ItFileSetHt != SingleSerieUIDFileSetHT.end() )
+      return ItFileSetHt->second;
+   return NULL;
+}
+
+/**
+ * \brief   accessor (DEPRECATED :  use GetNextSingleSerieUIDFileSet )
+ *          Warning : 'coherent' means here they have the same Serie UID
+ * \note : meaningfull only if GetFirstCoherentFileList() already called 
+ * @return  The next FileList if found, otherwhise NULL
+ */
+FileList *SerieHelper::GetNextCoherentFileList()
+{
+   gdcmAssertMacro (ItFileSetHt != SingleSerieUIDFileSetHT.end());
+  
+   ++ItFileSetHt;
+   if ( ItFileSetHt != SingleSerieUIDFileSetHT.end() )
+      return ItFileSetHt->second;
+   return NULL;
+}
+
+/**
+ * \brief   accessor (DEPRECATED :  use GetSingleSerieUIDFileSet )
+  *          Warning : 'coherent' means here they have the same Serie UID
+ * @param SerieUID SerieUID
+ * \return  pointer to the FileList if found, otherwhise NULL
+ */
+FileList *SerieHelper::GetCoherentFileList(std::string SerieUID)
+{
+   if ( SingleSerieUIDFileSetHT.count(SerieUID) == 0 )
+      return 0;     
+   return SingleSerieUIDFileSetHT[SerieUID];
+}
+#endif
+
+
+/**
+ * \brief   Get the first Fileset while visiting the SingleSerieUIDFileSetmap
+ * @return  The first FileList (SingleSerieUIDFileSet) if found, otherwhise 0
+ */
+FileList *SerieHelper::GetFirstSingleSerieUIDFileSet()
+{
+   ItFileSetHt = SingleSerieUIDFileSetHT.begin();
+   if ( ItFileSetHt != SingleSerieUIDFileSetHT.end() )
+      return ItFileSetHt->second;
+   return NULL;
+}
+
+/**
+ * \brief   Get the next Fileset while visiting the SingleSerieUIDFileSetmap
+ * \note : meaningfull only if GetNextSingleSerieUIDFileSet() already called 
+ * @return  The next FileList (SingleSerieUIDFileSet) if found, otherwhise 0
+ */
+FileList *SerieHelper::GetNextSingleSerieUIDFileSet()
+{
+   gdcmAssertMacro (ItFileSetHt != SingleSerieUIDFileSetHT.end());
+  
+   ++ItFileSetHt;
+   if ( ItFileSetHt != SingleSerieUIDFileSetHT.end() )
+      return ItFileSetHt->second;
+   return NULL;
+}
+
+/**
+ * \brief   Get the SingleSerieUIDFileSet according to its Serie UID
+ * @param SerieUID SerieUID to retrieve
+ * \return pointer to the FileList (SingleSerieUIDFileSet) if found, otherwhise 0
+ */
+FileList *SerieHelper::GetSingleSerieUIDFileSet(std::string SerieUID)
+{
+   if ( SingleSerieUIDFileSetHT.count(SerieUID) == 0 )
+      return 0;     
+   return SingleSerieUIDFileSetHT[SerieUID];
+}
+
+/**
+ * \brief   Splits a Single SerieUID Fileset according to the Orientations
+ * @param fileSet File Set to be splitted
+ * \return  std::map of 'Xcoherent' File sets
+ */
+
+XCoherentFileSetmap SerieHelper::SplitOnOrientation(FileList *fileSet)
+{
+   XCoherentFileSetmap CoherentFileSet;
+
+   int nb = fileSet->size();
+   if (nb == 0 )
+      return CoherentFileSet;
+   float iop[6];
+   std::string strOrient;
+   itksys_ios::ostringstream ossOrient;
+
+   FileList::const_iterator it = fileSet->begin();
+   it ++;
+   for ( ;
+         it != fileSet->end();
+       ++it)
+   {     
+      // Information is in :      
+      // 0020 0037 : Image Orientation (Patient) or
+      // 0020 0035 : Image Orientation (RET)
+
+      // Let's build again the 'cosines' string, to be sure of it's format      
+      (*it)->GetImageOrientationPatient(iop);
+
+      ossOrient << iop[0];      
+      for (int i = 1; i < 6; i++)
+      {
+        ossOrient << "\\";
+        ossOrient << iop[i]; 
+      }      
+      strOrient = ossOrient.str();
+      ossOrient.str("");
+      if ( CoherentFileSet.count(strOrient) == 0 )
+      {
+         gdcmDebugMacro(" New Orientation :[" << strOrient << "]");
+         // create a File set in 'orientation' position
+         CoherentFileSet[strOrient] = new FileList;
+      }
+      // Current Orientation and DICOM header match; add the file:
+      CoherentFileSet[strOrient]->push_back( (*it) );
+   }
+   return CoherentFileSet;
+}
+
+/**
+ * \brief   Splits a 'Single SerieUID' Fileset according to the Positions
+ * @param fileSet File Set to be splitted
+ * \return  std::map of 'Xcoherent' File sets
+ */
+
+XCoherentFileSetmap SerieHelper::SplitOnPosition(FileList *fileSet)
+{
+   XCoherentFileSetmap CoherentFileSet;
+
+   int nb = fileSet->size();
+   if (nb == 0 )
+      return CoherentFileSet;
+   float pos[3];
+   std::string strImPos;  // read on disc
+   itksys_ios::ostringstream ossPosition;
+   std::string strPosition; // re computed
+   FileList::const_iterator it = fileSet->begin();
+   it ++;
+   for ( ;
+         it != fileSet->end();
+       ++it)
+   {     
+      // Information is in :      
+      // 0020,0032 : Image Position Patient
+      // 0020,0030 : Image Position (RET)
+
+      strImPos = (*it)->GetEntryValue(0x0020,0x0032);
+      if ( strImPos == GDCM_UNFOUND)
+      {
+         gdcmWarningMacro( "Unfound Image Position Patient (0020,0032)");
+         strImPos = (*it)->GetEntryValue(0x0020,0x0030); // For ACR-NEMA images
+         if ( strImPos == GDCM_UNFOUND )
+         {
+            gdcmWarningMacro( "Unfound Image Position (RET) (0020,0030)");
+            // User wants to split on the 'Position'
+            // No 'Position' info found.
+            // We return an empty Htable !
+            return CoherentFileSet;
+         }  
+      }
+
+      if ( sscanf( strImPos.c_str(), "%f \\%f \\%f ", 
+                                              &pos[0], &pos[1], &pos[2]) != 3 )
+      {
+            gdcmWarningMacro( "Wrong number for Position : ["
+                       << strImPos << "]" );
+             return CoherentFileSet;
+      }
+
+      // Let's build again the 'position' string, to be sure of it's format      
+
+      ossPosition << pos[0];      
+      for (int i = 1; i < 3; i++)
+      {
+        ossPosition << "\\";
+        ossPosition << pos[i]; 
+      }      
+      strPosition = ossPosition.str();
+      ossPosition.str("");
+
+      if ( CoherentFileSet.count(strPosition) == 0 )
+      {
+         gdcmDebugMacro(" New Position :[" << strPosition << "]");
+         // create a File set in 'position' position
+         CoherentFileSet[strPosition] = new FileList;
+      }
+      // Current Position and DICOM header match; add the file:
+      CoherentFileSet[strPosition]->push_back( (*it) );
+   }   
+   return CoherentFileSet;
+}
+
+/**
+ * \brief   Splits a 'Single SerieUID' File set Coherent according to the
+ *          value of a given Tag
+ * @param fileSet File Set to be splitted
+ * @param   group  group number of the target Element
+ * @param   elem element number of the target Element
+ * \return  std::map of 'Xcoherent' File sets
+ */
+
+XCoherentFileSetmap SerieHelper::SplitOnTagValue(FileList *fileSet, 
+                                               uint16_t group, uint16_t element)
+{
+   XCoherentFileSetmap CoherentFileSet;
+
+   int nb = fileSet->size();
+   if (nb == 0 )
+      return CoherentFileSet;
+
+   std::string strTagValue;  // read on disc
+
+   FileList::const_iterator it = fileSet->begin();
+   it ++;
+   for ( ;
+         it != fileSet->end();
+       ++it)
+   {     
+      // Information is in :      
+      // 0020,0032 : Image Position Patient
+      // 0020,0030 : Image Position (RET)
+
+      strTagValue = (*it)->GetEntryValue(group,element);
+      
+      if ( CoherentFileSet.count(strTagValue) == 0 )
+      {
+         gdcmDebugMacro(" New Tag Value :[" << strTagValue << "]");
+         // create a File set in 'position' position
+         CoherentFileSet[strTagValue] = new FileList;
+      }
+      // Current Tag value and DICOM header match; add the file:
+      CoherentFileSet[strTagValue]->push_back( (*it) );
+   }
+   return CoherentFileSet;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \brief sorts the images, according to their Patient Position.
+ *
+ *  We may order, considering :
+ *   -# Image Position Patient
+ *   -# Image Number
+ *   -# file name
+ *   -# More to come :-)
+ * \note : FileList = std::vector<File* >
+ * @param fileList Coherent File list (same Serie UID) to sort
+ * @return false only if the header is bugged !
+ */
+bool SerieHelper::ImagePositionPatientOrdering( FileList *fileList )
+//based on Jolinda Smith's algorithm
+{
+   //iop is calculated based on the file file
+   float cosines[6];
+   double normal[3];
+   double ipp[3];
+   double dist;
+   double min = 0, max = 0;
+   bool first = true;
+
+   std::multimap<double,File *> distmultimap;
+   // Use a multimap to sort the distances from 0,0,0
+   for ( FileList::const_iterator 
+         it = fileList->begin();
+         it != fileList->end(); ++it )
+   {
+      if ( first ) 
+      {
+         (*it)->GetImageOrientationPatient( cosines );
+      
+         // You only have to do this once for all slices in the volume. Next, 
+         // for each slice, calculate the distance along the slice normal 
+         // using the IPP ("Image Position Patient") tag.
+         // ("dist" is initialized to zero before reading the first slice) :
+         normal[0] = cosines[1]*cosines[5] - cosines[2]*cosines[4];
+         normal[1] = cosines[2]*cosines[3] - cosines[0]*cosines[5];
+         normal[2] = cosines[0]*cosines[4] - cosines[1]*cosines[3];
+  
+         ipp[0] = (*it)->GetXOrigin();
+         ipp[1] = (*it)->GetYOrigin();
+         ipp[2] = (*it)->GetZOrigin();
+
+         dist = 0;
+         for ( int i = 0; i < 3; ++i )
+         {
+            dist += normal[i]*ipp[i];
+         }
+    
+         distmultimap.insert(std::pair<const double,File *>(dist, *it));
+
+         max = min = dist;
+         first = false;
+      }
+      else 
+      {
+         ipp[0] = (*it)->GetXOrigin();
+         ipp[1] = (*it)->GetYOrigin();
+         ipp[2] = (*it)->GetZOrigin();
+
+         dist = 0;
+         for ( int i = 0; i < 3; ++i )
+         {
+            dist += normal[i]*ipp[i];
+         }
+
+         distmultimap.insert(std::pair<const double,File *>(dist, *it));
+
+         min = (min < dist) ? min : dist;
+         max = (max > dist) ? max : dist;
+      }
+   }
+
+   // Find out if min/max are coherent
+   if ( min == max )
+   {
+     gdcmWarningMacro("Looks like all images have the exact same image position"
+                      << ". No PositionPatientOrdering sort performed" );
+     return false;
+   }
+
+   // Check to see if image shares a common position
+   bool ok = true;
+   for (std::multimap<double, File *>::iterator it2 = distmultimap.begin();
+        it2 != distmultimap.end();
+        ++it2)
+   {
+      if (distmultimap.count((*it2).first) != 1)
+      {
+         gdcmErrorMacro("File: "
+              << ((*it2).second->GetFileName())
+              << " Distance: "
+              << (*it2).first
+              << " position is not unique");
+
+         ok = false;
+      }
+   }
+   if (!ok)
+   {
+      return false;
+   }
+
+   fileList->clear();  // doesn't delete list elements, only nodes
+
+   if (DirectOrder)
+   {  
+      for (std::multimap<double, File *>::iterator it3 = distmultimap.begin();
+           it3 != distmultimap.end();
+           ++it3)
+      {
+         fileList->push_back( (*it3).second );
+      }
+   }
+   else // user asked for reverse order
+   {
+      std::multimap<double, File *>::const_iterator it4;
+      it4 = distmultimap.end();
+      do
+      {
+         it4--;
+         fileList->push_back( (*it4).second );
+      } while (it4 != distmultimap.begin() );
+   }
+
+   distmultimap.clear();
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+static bool ImageNumberLessThan(File *file1, File *file2)
+{
+  return file1->GetImageNumber() < file2->GetImageNumber();
+}
+static bool ImageNumberGreaterThan (File *file1, File *file2)
+{
+  return file1->GetImageNumber() > file2->GetImageNumber();
+}
+static bool FileNameLessThan (File *file1, File *file2)
+{
+   return file1->GetFileName() < file2->GetFileName();
+}
+static bool FileNameGreaterThan (File *file1, File *file2)
+{
+   return file1->GetFileName() > file2->GetFileName();
+}
+
+class SortFunctor
+{
+public:
+  bool operator() (File *file1, File *file2)
+    {
+    return (SortFunction)(file1, file2);
+    }
+  BOOL_FUNCTION_PFILE_PFILE_POINTER SortFunction;
+  SortFunctor()
+    {
+    SortFunction = 0;
+    }
+  SortFunctor(SortFunctor const &sf)
+    {
+    SortFunction = sf.SortFunction;
+    }
+  void operator=(BOOL_FUNCTION_PFILE_PFILE_POINTER sf)
+    {
+    SortFunction = sf;
+    }
+};
+
+//-----------------------------------------------------------------------------
+// Sort
+/**
+ * \brief   Sort FileList.
+ */
+static void Sort(FileList *fileList, SortFunctor &sf)
+{
+  std::sort(fileList->begin(), fileList->end(), sf );
+}
+
+
+/**
+ * \brief sorts the images, according to their Image Number
+ * \note Works only on bona fide files  (i.e image number is a character string
+ *                                      corresponding to an integer)
+ *             within a bona fide serie (i.e image numbers are consecutive)
+ * @param fileList File set (same Serie UID) to sort 
+ * @return false if non bona fide stuff encountered
+ */
+bool SerieHelper::ImageNumberOrdering(FileList *fileList) 
+{
+   int min, max, pos;
+   int n = fileList->size();
+
+   FileList::const_iterator it = fileList->begin();
+   min = max = (*it)->GetImageNumber();
+
+   for (; it != fileList->end(); ++it, ++n)
+   {
+      pos = (*it)->GetImageNumber();
+      min = (min < pos) ? min : pos;
+      max = (max > pos) ? max : pos;
+   }
+
+   // Find out if image numbers are coherent (consecutive)
+   if ( min == max || max == 0 || max >= (n+min) )
+   {
+      gdcmWarningMacro( " 'Image numbers' not coherent. "
+                        << " No ImageNumberOrdering sort performed.");
+      return false;
+   }
+   SortFunctor sf;
+   if (DirectOrder)
+     sf = ImageNumberLessThan;
+   else
+     sf = ImageNumberGreaterThan;
+   Sort(fileList, sf);
+
+   return true;
+}
+/**
+ * \brief sorts the images, according to their File Name
+ * @param fileList Coherent File list (same Serie UID) to sort
+ * @return false only if the header is bugged !
+ */
+bool SerieHelper::FileNameOrdering(FileList *fileList)
+{
+   SortFunctor sf;
+   if (DirectOrder) 
+      sf = FileNameLessThan;
+   else
+      sf = FileNameGreaterThan;
+   Sort(fileList, sf);
+
+   return true;
+}
+
+/**
+ * \brief sorts the images, according to user supplied function
+ * @param fileList Coherent File list (same Serie UID) to sort
+ * @return false only if the header is bugged !
+ */
+bool SerieHelper::UserOrdering(FileList *fileList)
+{
+   SortFunctor sf;
+   sf = SerieHelper::UserLessThanFunction;
+   Sort(fileList,sf);
+   if (!DirectOrder) 
+   {
+      std::reverse(fileList->begin(), fileList->end());
+   }
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Canonical printer.
+ */
+void SerieHelper::Print(std::ostream &os, std::string const &indent)
+{
+   // For all the Coherent File lists of the gdcm::Serie
+   SingleSerieUIDFileSetmap::iterator itl = SingleSerieUIDFileSetHT.begin();
+   if ( itl == SingleSerieUIDFileSetHT.end() )
+   {
+      gdcmWarningMacro( "No SingleSerieUID File set found" );
+      return;
+   }
+   while (itl != SingleSerieUIDFileSetHT.end())
+   { 
+      os << "Serie UID :[" << itl->first << "]" << std::endl;
+
+      // For all the files of a SingleSerieUID File set
+      for (FileList::iterator it =  (itl->second)->begin();
+                                  it != (itl->second)->end(); 
+                                ++it)
+      {
+         os << indent << " --- " << (*it)->GetFileName() << std::endl;
+      }
+      ++itl;
+   }
+}
+
+void SerieHelper::CreateDefaultUniqueSeriesIdentifier()
+{
+   // If the user requests, additional information can be appended
+   // to the SeriesUID to further differentiate volumes in the DICOM
+   // objects being processed.
+ 
+   // 0020 0011 Series Number
+   // A scout scan prior to a CT volume scan can share the same
+   //   SeriesUID, but they will sometimes have a different Series Number
+   AddRestriction( 0x0020, 0x0011);
+   // 0018 0024 Sequence Name
+   // For T1-map and phase-contrast MRA, the different flip angles and
+   //   directions are only distinguished by the Sequence Name
+   AddRestriction(0x0018, 0x0024);
+   // 0018 0050 Slice Thickness
+   // On some CT systems, scout scans and subsequence volume scans will
+   //   have the same SeriesUID and Series Number - YET the slice 
+   //   thickness will differ from the scout slice and the volume slices.
+   AddRestriction(0x0018, 0x0050);
+   // 0028 0010 Rows
+   // If the 2D images in a sequence don't have the same number of rows,
+   // then it is difficult to reconstruct them into a 3D volume.
+   AddRestriction(0x0028, 0x0010);
+   // 0028 0011 Columns
+   // If the 2D images in a sequence don't have the same number of columns,
+   // then it is difficult to reconstruct them into a 3D volume.
+   AddRestriction(0x0028, 0x0011);
+}
+
+/**
+ * \brief Heuristics to *try* to build a Serie Identifier that would ensure
+ *        all the images are coherent.
+ *
+ * By default, uses the SeriesUID.  If UseSeriesDetails(true) has been called,
+ *         then additional identifying information is used.
+ *  We allow user to add his own critierions, using AddSeriesDetail
+ *        (he knows more than we do about his images!)
+ *        ex : in tagging series, the only pertnent tag is
+ *        0018|1312 [In-plane Phase Encoding Direction] value : ROW/COLUMN
+ * @param inFile gdcm::File we want to build a Serie Identifier for.
+ * @return the SeriesIdentifier
+ */
+std::string SerieHelper::CreateUniqueSeriesIdentifier( File *inFile )
+{
+   if( inFile->IsReadable() )
+   {
+    // 0020 000e UI REL Series Instance UID
+    std::string uid = inFile->GetEntryValue (0x0020, 0x000e);
+    std::string id = uid.c_str();
+    if(m_UseSeriesDetails)
+      {
+      for(SerieExRestrictions::iterator it2 = ExRefine.begin();
+        it2 != ExRefine.end();
+        ++it2)
+        {
+        const ExRule &r = *it2;
+        std::string s = inFile->GetEntryValue( r.group, r.elem );
+        if( s == gdcm::GDCM_UNFOUND )
+          {
+          s = "";
+          }
+        if( id == uid && !s.empty() )
+          {
+          id += "."; // add separator
+          }
+        id += s;
+        }
+      }
+    // Eliminate non-alnum characters, including whitespace...
+    //   that may have been introduced by concats.
+    for(unsigned int i=0; i<id.size(); i++)
+      {
+      while(i<id.size() 
+        && !( id[i] == '.'
+          || (id[i] >= 'a' && id[i] <= 'z')
+          || (id[i] >= '0' && id[i] <= '9')
+          || (id[i] >= 'A' && id[i] <= 'Z')))
+        {
+        id.erase(i, 1);
+        }
+      }
+    return id;
+    }
+  else // Could not open inFile
+    {
+    gdcmWarningMacro("Could not parse series info.");
+    std::string id = gdcm::GDCM_UNFOUND;
+    return id;
+    }
+}
+
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmSerieHelper.h b/Utilities/ITK/Utilities/gdcm/src/gdcmSerieHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..b7fa4ba568587fa3000a75bf5a763eb529b8d8f7
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmSerieHelper.h
@@ -0,0 +1,223 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmSerieHelper.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 18:29:59 $
+  Version:   $Revision: 1.11 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMSERIEHELPER_H
+#define GDCMSERIEHELPER_H
+
+#include "gdcmCommon.h" 
+#include "gdcmDebug.h"  // for LEGACY
+ 
+#include <vector>
+#include <iostream>
+#include <map>
+#include <stdio.h> // for sscanf
+
+namespace gdcm 
+{
+class File;
+
+   typedef std::vector<File* > FileList;
+#ifndef GDCM_LEGACY_REMOVE
+typedef std::vector<File* > GdcmFileList;
+#endif
+
+   /// \brief XCoherent stands for 'Extra Coherent',
+   ///        (The name 'Coherent' would be enough but it was used before;
+   ///        I don't want to put a bomb in the code)
+   ///        Any 'better name' is welcome !
+   typedef std::map<std::string, FileList *> XCoherentFileSetmap;
+
+   typedef bool (*BOOL_FUNCTION_PFILE_PFILE_POINTER)(File *, File *);
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief  
+ *  This class should be used for a stack of 2D dicom images.
+ *   
+ *   - It allows to explore (recursively or not) a directory and 
+ *   makes a set of 'Coherent Files' lists (coherent : same SerieUID)
+ *   - It allows :
+ *   - - to sort any of the Coherent File list on the image position.
+ *   - - to split any of the Single SerieUID Filesets (better use this name than
+ *   'Coherent File List' : it's NOT a std::list, files are NOT coherent ...)
+ *    into several XCoherent Filesets 
+ *   XCoherent stands for 'Extra Coherent' (same orientation, or same position)
+ */
+class GDCM_EXPORT SerieHelper 
+{
+public:
+   /// SingleSerieUIDFileSetmap replaces the former CoherentFileListmap
+   /// ( List were actually std::vectors, and wher no coherent at all :
+   ///   They were only Single SeriesInstanceUID File sets)
+   typedef std::map<std::string, FileList *> SingleSerieUIDFileSetmap;
+
+   typedef std::vector<File* > FileVector;
+
+   SerieHelper();
+   ~SerieHelper();
+   void Print(std::ostream &os = std::cout, std::string const &indent = "" );
+
+   /// \todo should return bool or throw error ?
+   void AddFileName(std::string const &filename);
+   bool AddFile(File *header);
+#ifndef GDCM_LEGACY_REMOVE
+   bool AddGdcmFile(File* header) { return AddFile(header); }
+#endif
+
+   void SetDirectory(std::string const &dir, bool recursive=false);
+   bool IsCoherent(FileList *fileSet);
+   void OrderFileList(FileList *fileSet);
+   void Clear() { ClearAll(); }
+
+   /// \brief Gets the FIRST Single SerieUID Fileset.
+   ///        Deprecated; kept not to break the API
+   /// \note Caller must call OrderFileList first
+   /// @return the (first) Single SerieUID Fileset
+   const FileList &GetFileList()
+                           { return *SingleSerieUIDFileSetHT.begin()->second; }
+  
+   GDCM_LEGACY(   FileList *GetFirstCoherentFileList()  );
+   GDCM_LEGACY(   FileList *GetNextCoherentFileList()   );
+   GDCM_LEGACY(   FileList *GetCoherentFileList(std::string serieUID)  );
+
+   FileList *GetFirstSingleSerieUIDFileSet();
+   FileList *GetNextSingleSerieUIDFileSet();
+   FileList *GetSingleSerieUIDFileSet(std::string serieUID);
+   /// brief returns the 'Series Instance UID' Single SerieUID FileSet
+   std::string GetCurrentSerieUIDFileSetUID()
+                             { return  (*ItFileSetHt).first; }
+   /// All the following allow user to restrict DICOM file to be part
+   /// of a particular serie
+   GDCM_LEGACY( void AddRestriction(TagKey const &key, std::string const &value) );
+   /// Allow user to specify that the serie should also be consistent (== operation),
+   /// on the particular tag (group,element)
+   void AddRestriction(uint16_t group, uint16_t elem); 
+   /// Same as above accept use the format: "0x1234|0x5678"
+   void AddRestriction(const std::string & tag)
+     {
+     unsigned int group, element;
+     sscanf( tag.c_str(), "%04x|%04x", &group, &element);
+     AddRestriction( group, element );
+     }
+   /// Allow user to refine the selection of a serie by specifying operation (op) on a 
+   /// particular tag (group, elem) with a particular value (value).
+   void AddRestriction(uint16_t group, uint16_t elem, 
+                       std::string const &value, int op);
+
+   /// \brief Use additional series information such as ProtocolName
+   ///        and SeriesName to identify when a single SeriesUID contains
+   ///        multiple 3D volumes - as can occur with perfusion and DTI imaging
+   void SetUseSeriesDetails( bool useSeriesDetails )
+     {
+     m_UseSeriesDetails = useSeriesDetails;
+     }
+   bool GetUseSeriesDetails()
+     {
+     return m_UseSeriesDetails;
+     }
+   /// \brief This function will add the following DICOM tag as being part of a
+   /// 'fake' uid. This is usefull when the Serie UID is not enough to disseminate
+   /// into multiple sub serie when needed:
+   /// 0020 0011 Series Number
+   /// 0018 0024 Sequence Name
+   /// 0018 0050 Slice Thickness
+   /// 0028 0010 Rows
+   /// 0028 0011 Columns
+   void CreateDefaultUniqueSeriesIdentifier();
+   /// \brief Create a string that uniquely identifies a series.   By default
+   //         uses the SeriesUID.   If UseSeriesDetails(true) has been called,
+   //         then additional identifying information is used.
+   std::string CreateUniqueSeriesIdentifier( File * inFile );
+ 
+/**
+ * \brief Sets the LoadMode as a boolean string. 
+ *        LD_NOSEQ, LD_NOSHADOW, LD_NOSHADOWSEQ
+ *        ... (nothing more, right now)
+ *        WARNING : before using LD_NOSHADOW, be sure *all* your files
+ *        contain accurate values in the 0x0000 element (if any) 
+ *        of *each* Shadow Group. The parser will fail if the size is wrong !
+ * @param   mode Load mode to be used    
+ */
+   void SetLoadMode (int mode) { LoadMode = mode; }
+
+/// Brief User wants the files to be sorted Direct Order (default value)
+   void SetSortOrderToDirect()  { DirectOrder = true;  }
+
+/// Brief User wants the files to be sorted Reverse Order 
+   void SetSortOrderToReverse() { DirectOrder = false; }
+
+   /// to allow user to give is own comparison function
+   void SetUserLessThanFunction( BOOL_FUNCTION_PFILE_PFILE_POINTER userFunc ) 
+                        { UserLessThanFunction = userFunc; }  
+
+   XCoherentFileSetmap SplitOnOrientation(FileList *fileSet); 
+   XCoherentFileSetmap SplitOnPosition(FileList *fileSet); 
+   XCoherentFileSetmap SplitOnTagValue(FileList *fileSet,
+                                               uint16_t group, uint16_t element);
+
+
+private:
+   void ClearAll();
+   bool UserOrdering(FileList *fileSet);
+   bool ImagePositionPatientOrdering(FileList *fileSet);
+   bool ImageNumberOrdering(FileList *fileSet);
+   bool FileNameOrdering(FileList *fileSet);
+   
+//Attributes:
+   
+   SingleSerieUIDFileSetmap SingleSerieUIDFileSetHT;
+   SingleSerieUIDFileSetmap::iterator ItFileSetHt;
+
+#ifndef GDCM_LEGACY_REMOVE
+   typedef std::pair<TagKey, std::string> Rule;
+   typedef std::vector<Rule> SerieRestrictions;
+   SerieRestrictions Restrictions;
+#endif
+
+   // New style for (extented) Rules
+   typedef struct {
+      uint16_t group;
+      uint16_t elem;
+      std::string value;
+      int op;
+   } ExRule;
+   typedef std::vector<ExRule> SerieExRestrictions;
+   SerieExRestrictions ExRestrictions;
+   SerieExRestrictions ExRefine;
+
+   /// \brief Bit string integer (each one considered as a boolean)
+   ///        Bit 0 : Skip Sequences,    if possible
+   ///        Bit 1 : Skip Shadow Groups if possible
+   ///        Probabely, some more to add
+   int LoadMode;
+
+   /// \brief whether we want to sort in direct order or not (reverse order).
+   ///        To be used by aware user only
+   bool DirectOrder;
+
+   /// \brief If user knows more about his images than gdcm does,
+   ///        he may supply his own comparison function.
+   BOOL_FUNCTION_PFILE_PFILE_POINTER UserLessThanFunction;
+
+   bool m_UseSeriesDetails;
+};
+
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmTS.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmTS.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..48d21358455e89caae2b89e7ddc3c2431dd6248e
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmTS.cxx
@@ -0,0 +1,365 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmTS.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:57 $
+  Version:   $Revision: 1.7 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmTS.h"
+#include "gdcmDebug.h"
+#include "gdcmUtil.h"
+#include "gdcmDictSet.h"
+
+#include <fstream>
+#include <string>
+#include <iostream>
+#include <ctype.h> // for isdigit
+
+// TODO
+// troubles expected with TS : 1.2.840.113619.5.2
+// Implicit VR - Big Endian
+// http://www.gemedicalsystemseurope.com/euen/it_solutions/pdf/lsqxi_rev2.pdf
+// G.E. deliberately violated a lot of Dicom rules are
+// (probabely to to avoid other people to read their images)
+// Just try and error on new images :
+// PrintFile debug filein=...
+// and fix the bugs
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/// \brief Transfer Syntaxes gdcm deals with (internal use only)
+static const char *SpecialStrings[] =  {
+  // Implicit VR Little Endian
+  "1.2.840.10008.1.2",
+  // Implicit VR Big Endian (G.E Private)
+  "1.2.840.113619.5.2",
+  // Explicit VR Little Endian
+  "1.2.840.10008.1.2.1",
+  // Deflated Explicit VR Little Endian
+  "1.2.840.10008.1.2.1.99",
+  // Explicit VR Big Endian
+  "1.2.840.10008.1.2.2",
+  // JPEG Baseline (Process 1)
+  "1.2.840.10008.1.2.4.50",
+  // JPEG Extended (Process 2 & 4)
+  "1.2.840.10008.1.2.4.51",
+  // JPEG Extended (Process 3 & 5)
+  "1.2.840.10008.1.2.4.52",
+  // JPEG Spectral Selection, Non-Hierarchical (Process 6 & 8)
+  "1.2.840.10008.1.2.4.53",
+  // JPEG Full Progression, Non-Hierarchical (Process 10 & 12)
+  "1.2.840.10008.1.2.4.55",
+  // JPEG Lossless, Non-Hierarchical (Process 14)
+  "1.2.840.10008.1.2.4.57",
+  // JPEG Lossless, Hierarchical, First-Order Prediction (Process 14,
+  //                                                       [Selection Value 1])
+  "1.2.840.10008.1.2.4.70",
+  // JPEG-LS Lossless Image Compression
+  "1.2.840.10008.1.2.4.80",
+  // JPEG-LS Lossy (Near-Lossless) Image Compression
+  "1.2.840.10008.1.2.4.81",
+  // JPEG 2000 Lossless
+  "1.2.840.10008.1.2.4.90",
+  // JPEG 2000
+  "1.2.840.10008.1.2.4.91",
+  // RLE Lossless
+  "1.2.840.10008.1.2.5",
+  // MPEG2 Main Profile @ Main Level
+  "1.2.840.10008.1.2.4.100",
+  // Unknown
+  "Unknown Transfer Syntax", // Pretty sure we never use this case...
+  NULL // Compilers have no obligation to finish by NULL, do it ourself
+};
+
+//-----------------------------------------------------------------------------
+/// \brief auto generated function, to fill up the Dicom Dictionnary,
+///       if relevant file is not found on user's disk
+void FillDefaultTSDict(TSHT &ts);
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+TS::TS() 
+{
+   std::string filename = DictSet::BuildDictPath() + DICT_TS;
+   std::ifstream from(filename.c_str());
+   if ( !from )
+   {
+      gdcmWarningMacro("Can't open dictionary" << filename.c_str());
+      FillDefaultTSDict( TsMap );
+   }
+   else
+   {
+      TSKey key;
+      TSAtr name;
+
+      while (!from.eof())
+      {
+         from >> key;
+         from >> std::ws;
+         std::getline(from, name);
+
+         if (key != "")
+         {
+            TsMap[key] = name;
+         }
+      }
+      from.close();
+   }
+}
+
+TS::~TS() 
+{
+   TsMap.clear();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+/// \brief returns occurence number of the given key
+int TS::Count(TSKey const &key) 
+{
+   return TsMap.count(key);
+}
+
+/// \brief returns the human readable value of a Transfer Syntax string 
+TSAtr const &TS::GetValue(TSKey const &key) 
+{
+   // First thing clean up the string 
+   // (sometimes the transfer syntax is padded with spaces)
+   std::string copy = key;
+   while ( copy.size() && !isdigit((unsigned char)copy[copy.size()-1]) )
+   {
+      copy.erase(copy.size()-1, 1);
+   }
+
+   TSHT::const_iterator it = TsMap.find(copy);
+   if (it == TsMap.end())
+   {
+      return GDCM_UNFOUND;
+   }
+   return it->second;
+}
+/**
+ * \brief   Determines if the key passed corresponds to a 'Transfer Syntax'
+ *          as defined in DICOM (and stored in gdcm::TS class)
+ * @return  True when key is an actual 'Transfer Syntax'. 
+ *          False in all other cases.
+ */
+bool TS::IsTransferSyntax(TSKey const &key)
+{
+   TSHT::const_iterator it = TsMap.find(key);
+   return it != TsMap.end();
+}
+
+/**
+ * \brief   Determines if the Transfer Syntax was already encountered
+ *          and if it corresponds to a Run Length Encoding Lossless one
+ * @return  True when Run Length Encoding Lossless found. 
+ *          False in all other cases.
+ */
+bool TS::IsRLELossless(TSKey const &key)
+{
+   bool r = false;
+   // First check this is an actual transfer syntax
+   if ( IsTransferSyntax(key) )
+   {
+      if ( key == SpecialStrings[RLELossless] )
+      {
+         r = true;
+      }
+   }
+   return r;
+}
+
+/**
+ * \brief   Determines if the Transfer Syntax was already encountered
+ *          and if it corresponds to a 'classical' JPEG Lossless one
+ * @return  True when 'classical' Lossless found. 
+ *          False in all other cases.
+ */
+bool TS::IsJPEGLossless(TSKey const &key)
+{
+   bool r = false;
+   // First check this is an actual transfer syntax
+   if ( IsTransferSyntax(key) )
+   {
+      if ( key == SpecialStrings[JPEGFullProgressionProcess10_12]
+        || key == SpecialStrings[JPEGLosslessProcess14]
+        || key == SpecialStrings[JPEGLosslessProcess14_1] )
+      {
+         r = true;
+      }
+   }
+   return r;
+}
+
+/**
+ * \brief   Determines if the Transfer Syntax was already encountered
+ *          and if it corresponds to a 'classical' JPEG Lossy one
+ * @return  True when 'classical' Lossy found. 
+ *          False in all other cases.
+ */
+bool TS::IsJPEGLossy(TSKey const &key)
+{
+   bool r = false;
+   // First check this is an actual transfer syntax
+   if ( IsTransferSyntax(key) )
+   {
+      if ( key == SpecialStrings[JPEGBaselineProcess1]
+        || key == SpecialStrings[JPEGExtendedProcess2_4]
+        || key == SpecialStrings[JPEGExtendedProcess3_5]
+        || key == SpecialStrings[JPEGSpectralSelectionProcess6_8] )
+      {
+         r = true;
+      }
+   }
+   return r;
+}
+
+/**
+ * \brief   Determines if the Transfer Syntax was already encountered
+ *          and if it corresponds to a JPEG2000 one
+ * @return  True when JPEG2000 (Lossly or LossLess) found. 
+ *          False in all other cases.
+ */
+bool TS::IsJPEG2000(TSKey const &key)
+{
+   bool r = false;
+   // First check this is an actual transfer syntax
+   if ( IsTransferSyntax(key) )
+   {
+      if ( key == SpecialStrings[JPEG2000Lossless]
+        || key == SpecialStrings[JPEG2000] )
+      {
+         r = true;
+      }
+   }
+   return r;
+}
+
+/**
+ * \brief   Determines if the Transfer Syntax corresponds to 
+ *          'classical' Jpeg Lossless or Jpeg lossy.
+ * @return  True when any form of JPEG found. False otherwise.
+ */
+bool TS::IsJPEG(TSKey const &key)
+{
+   bool r = false;
+   // First check this is an actual transfer syntax
+   if ( IsTransferSyntax(key) )
+   {
+      if ( IsJPEGLossy( key )
+        || IsJPEGLossless( key )
+        || IsJPEG2000( key )
+        || IsJPEGLS( key )
+         )
+      {
+         r = true;
+      }
+   }
+   return r;
+}
+
+/**
+ * \brief   Determines if the Transfer Syntax corresponds to any form
+ *          of Jpeg-LS encoded Pixel data.
+ * @return  True when any form of JPEG-LS found. False otherwise.
+ */
+bool TS::IsJPEGLS(TSKey const &key)
+{
+   bool r = false;
+   // First check this is an actual transfer syntax
+   if ( IsTransferSyntax(key) )
+   {
+      if ( key == SpecialStrings[JPEGLSLossless]
+        || key == SpecialStrings[JPEGLSNearLossless] ) 
+      {
+         r = true;
+      }
+   }
+   return r;
+}
+
+/**
+ * \brief   Determines if the Transfer Syntax corresponds to any form
+ *          of MPEG encoded Pixel data.
+ * @return  True when any form of MPEG found. False otherwise.
+ */
+bool TS::IsMPEG(TSKey const &key)
+{
+   bool r = false;
+   // First check this is an actual transfer syntax
+   if ( IsTransferSyntax(key) )
+   {
+      if ( key == SpecialStrings[MPEG2MainProfile] ) 
+      {
+         r = true;
+      }
+   }
+   return r;
+}
+
+/**
+ * \brief   GetSpecialTransferSyntax ??
+ * @param  key TSKey const &key ??
+ * @return  TS::SpecialType ??.
+ */
+TS::SpecialType TS::GetSpecialTransferSyntax(TSKey const &key)
+{
+   for (int i = 0; SpecialStrings[i] != NULL; i++)
+   {
+      if ( SpecialStrings[i] == key )
+      {
+         return SpecialType(i);
+      }
+   }
+   return UnknownTS;
+}
+
+/**
+ * \brief   GetSpecialTransferSyntax ??
+ * @param  t SpecialType t ??
+ * @return  char* TS : SpecialStrings[t] ??.
+ */
+const char* TS::GetSpecialTransferSyntax(SpecialType t)
+{
+   return SpecialStrings[t];
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Print all 
+ * @param   os The output stream to be written to.
+ */
+void TS::Print(std::ostream &os,std::string const &)
+{
+   itksys_ios::ostringstream s;
+
+   for (TSHT::const_iterator it = TsMap.begin(); it != TsMap.end(); ++it)
+   {
+      s << "TS : " << it->first << " = " << it->second << std::endl;
+   }
+   os << s.str();
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmTS.h b/Utilities/ITK/Utilities/gdcm/src/gdcmTS.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b2d7032b162997ea52442410db6b6f3cc9741cd
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmTS.h
@@ -0,0 +1,94 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmTS.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMTS_H
+#define GDCMTS_H
+
+#include "gdcmCommon.h"
+
+#include <map>
+#include <string>
+#include <iostream>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+typedef std::string TSKey;
+typedef std::string TSAtr;
+typedef std::map<TSKey, TSAtr> TSHT;    // Transfer Syntax Hash Table
+
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief Container for dicom 'Transfer Syntax' Hash Table
+ * \note   This is a singleton
+ */
+class GDCM_EXPORT TS
+{
+public:
+enum SpecialType {
+   ImplicitVRLittleEndian = 0,
+   ImplicitVRBigEndianPrivateGE,
+   ExplicitVRLittleEndian,
+   DeflatedExplicitVRLittleEndian,
+   ExplicitVRBigEndian,
+   JPEGBaselineProcess1,
+   JPEGExtendedProcess2_4,
+   JPEGExtendedProcess3_5,
+   JPEGSpectralSelectionProcess6_8,
+   JPEGFullProgressionProcess10_12,
+   JPEGLosslessProcess14,
+   JPEGLosslessProcess14_1,
+   JPEGLSLossless,
+   JPEGLSNearLossless,
+   JPEG2000Lossless,  
+   JPEG2000,
+   RLELossless,
+   MPEG2MainProfile,  
+   UnknownTS
+};
+
+public:
+   TS();
+   ~TS();
+
+   void Print(std::ostream &os = std::cout,
+              std::string const &s = "");
+
+   int Count(TSKey const &key);
+   TSAtr const &GetValue(TSKey const &key);
+   bool IsTransferSyntax(TSKey const &key);
+   bool IsRLELossless(TSKey const &key);
+   bool IsJPEGLossless(TSKey const&key);
+   bool IsJPEGLossy(TSKey const&key);
+   bool IsJPEG2000(TSKey const &key);
+   bool IsJPEG(TSKey const &key);
+   bool IsJPEGLS(TSKey const &key);
+   bool IsMPEG(TSKey const &key);
+
+   // This should be deprecated very soon
+   SpecialType GetSpecialTransferSyntax(TSKey const &key);
+   const char* GetSpecialTransferSyntax(SpecialType t);
+
+private:
+   TSHT TsMap;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmUtil.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmUtil.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ac993725a5361fea73997f1a46cc23e8435105de
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmUtil.cxx
@@ -0,0 +1,1176 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmUtil.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:58 $
+  Version:   $Revision: 1.37 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+
+#include <iostream>
+#include <stdarg.h> // for va_list
+
+// For GetCurrentDate, GetCurrentTime
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__)
+#include <sys/timeb.h>
+#else
+#include <sys/time.h>
+#endif
+
+#include <stdarg.h>  //only included in implementation file
+#include <stdio.h>   //only included in implementation file
+
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__)
+   #include <winsock.h>  // for gethostname and gethostbyname and GetTickCount...
+// I haven't find a way to determine wether we need to under GetCurrentTime or not...
+// I think the best solution would simply to get rid of this problematic function
+// and use a 'less' common name...
+#if !defined(__BORLANDC__) || (__BORLANDC__ >= 0x0560)
+   #undef GetCurrentTime
+#endif
+#else
+   #include <unistd.h>  // for gethostname
+   #include <netdb.h>   // for gethostbyname
+#endif
+
+// For GetMACAddress
+#ifdef _WIN32
+   #include <snmp.h>
+   #include <conio.h>
+#else
+   #include <unistd.h>
+   #include <stdlib.h>
+   #include <string.h>
+   #include <sys/types.h>
+#endif
+
+#ifdef CMAKE_HAVE_SYS_IOCTL_H
+   #include <sys/ioctl.h>  // For SIOCGIFCONF on Linux
+#endif
+#ifdef CMAKE_HAVE_SYS_SOCKET_H
+   #include <sys/socket.h>
+#endif
+#ifdef CMAKE_HAVE_SYS_SOCKIO_H
+   #include <sys/sockio.h>  // For SIOCGIFCONF on SunOS
+#endif
+#ifdef CMAKE_HAVE_NET_IF_H
+   #include <net/if.h>
+#endif
+#ifdef CMAKE_HAVE_NETINET_IN_H
+   #include <netinet/in.h>   //For IPPROTO_IP
+#endif
+#ifdef CMAKE_HAVE_NET_IF_DL_H
+   #include <net/if_dl.h>
+#endif
+#if defined(CMAKE_HAVE_NET_IF_ARP_H) && defined(__sun)
+   // This is absolutely necessary on SunOS
+   #include <net/if_arp.h>
+#endif
+
+// For GetCurrentThreadID()
+#ifdef __linux__
+   #include <sys/types.h>
+   #include <linux/unistd.h>
+#endif
+#ifdef __sun
+   #include <thread.h>
+#endif
+
+namespace gdcm 
+{
+//-------------------------------------------------------------------------
+const std::string Util::GDCM_UID = "1.2.826.0.1.3680043.2.1143";
+std::string Util::RootUID        = GDCM_UID;
+/*
+ * File Meta Information Version (0002,0001) shall contain a two byte OB 
+ * value consisting of a 0x00 byte, followed by 0x01 byte, and not the 
+ * value 0x0001 encoded as a little endian 16 bit short value, 
+ * which would be the other way around...
+ */
+const uint16_t Util::FMIV = 0x0100;
+uint8_t *Util::FileMetaInformationVersion = (uint8_t *)&FMIV;
+std::string Util::GDCM_MAC_ADRESS = GetMACAddress();
+
+//-------------------------------------------------------------------------
+// Public
+/**
+ * \brief Provide a better 'c++' approach for sprintf
+ * For example c code is:
+ * char result[2048]; // hope 2048 is enough
+ * sprintf(result, "%04x|%04x", group , elem);
+ *
+ * c++ code is 
+ * itksys_ios::ostringstream buf;
+ * buf << std::right << std::setw(4) << std::setfill('0') << std::hex
+ *     << group << "|" << std::right << std::setw(4) << std::setfill('0') 
+ *     << std::hex <<  elem;
+ * buf.str();
+ *
+ * gdcm style code is
+ * string result;
+ * result = gdcm::Util::Format("%04x|%04x", group , elem);
+ */
+std::string Util::Format(const char *format, ...)
+{
+   char buffer[2048]; // hope 2048 is enough
+   va_list args;
+   va_start(args, format);
+   vsprintf(buffer, format, args);  //might be a security flaw
+   va_end(args); // Each invocation of va_start should be matched 
+                 // by a corresponding invocation of va_end
+                 // args is then 'undefined'
+   return buffer;
+}
+
+
+/**
+ * \brief Because not available in C++ (?)
+ * @param str string to check
+ * @param tokens std::vector to receive the tokenized substrings
+ * @param delimiters string containing the character delimitors
+ 
+ */
+void Util::Tokenize (const std::string &str,
+                     std::vector<std::string> &tokens,
+                     const std::string &delimiters)
+{
+   std::string::size_type lastPos = str.find_first_not_of(delimiters,0);
+   std::string::size_type pos     = str.find_first_of    (delimiters,lastPos);
+   while (std::string::npos != pos || std::string::npos != lastPos)
+   {
+      tokens.push_back(str.substr(lastPos, pos - lastPos));
+      lastPos = str.find_first_not_of(delimiters, pos);
+      pos     = str.find_first_of    (delimiters, lastPos);
+   }
+}
+
+/**
+ * \brief Because not available in C++ (?)
+ *        Counts the number of occurences of a substring within a string
+ * @param str string to check
+ * @param subStr substring to count
+ */
+ 
+int Util::CountSubstring (const std::string &str,
+                          const std::string &subStr)
+{
+   int count = 0;                 // counts how many times it appears
+   std::string::size_type x = 0;  // The index position in the string
+
+   do
+   {
+      x = str.find(subStr,x);     // Find the substring
+      if (x != std::string::npos) // If present
+      {
+         count++;                 // increase the count
+         x += subStr.length();    // Skip this word
+      }
+   }
+   while (x != std::string::npos);// Carry on until not present
+
+   return count;
+}
+
+/**
+ * \brief  Checks whether a 'string' is printable or not (in order
+ *         to avoid corrupting the terminal of invocation when printing)
+ * @param s string to check
+ */
+bool Util::IsCleanString(std::string const &s)
+{
+   for(unsigned int i=0; i<s.size(); i++)
+   {
+      if (!isprint((unsigned char)s[i]) )
+      {
+         return false;
+      }
+   }
+   return true;   
+}
+
+/**
+ * \brief  Checks whether an 'area' is printable or not (in order
+ *         to avoid corrupting the terminal of invocation when printing)
+ * @param s area to check (uint8_t is just for prototyping. feel free to cast)
+ * @param l area length to check
+ */
+bool Util::IsCleanArea(uint8_t *s, int l)
+{
+   for( int i=0; i<l; i++)
+   {
+      if (!isprint((unsigned char)s[i]) )
+      {
+         return false;
+      }
+   }
+   return true;   
+}
+/**
+ * \brief  Weed out a string from the non-printable characters (in order
+ *         to avoid corrupting the terminal of invocation when printing)
+ * @param s string to check (uint8_t is just for prototyping. feel free to cast)
+ */
+std::string Util::CreateCleanString(std::string const &s)
+{
+   std::string str = s;
+
+   for(unsigned int i=0; i<str.size(); i++)
+   {
+      if (!isprint((unsigned char)str[i]) )
+      {
+         str[i] = '.';
+      }
+   }
+
+   if (str.size() > 0 )
+   {
+      if (!isprint((unsigned char)s[str.size()-1]) )
+      {
+         if (s[str.size()-1] == 0 )
+         {
+            str[str.size()-1] = ' ';
+         }
+      }
+   }
+
+   return str;
+}
+
+/**
+ * \brief  Weed out a string from the non-printable characters (in order
+ *         to avoid corrupting the terminal of invocation when printing)
+ * @param s area to process (uint8_t is just for prototyping. feel free to cast)
+ * @param l area length to check
+ */
+std::string Util::CreateCleanString(uint8_t *s, int l)
+{
+   std::string str;
+
+   for( int i=0; i<l; i++)
+   {
+      if (!isprint((unsigned char)s[i]) )
+      {
+         str = str + '.';
+      }
+   else
+      {
+         str = str + (char )s[i];
+      }
+   }
+
+   return str;
+}
+/**
+ * \brief   Add a SEPARATOR to the end of the name if necessary
+ * @param   pathname file/directory name to normalize 
+ */
+std::string Util::NormalizePath(std::string const &pathname)
+{
+   const char SEPARATOR_X      = '/';
+   const char SEPARATOR_WIN    = '\\';
+   const std::string SEPARATOR = "/";
+   std::string name = pathname;
+   int size = name.size();
+
+   if ( name[size-1] != SEPARATOR_X && name[size-1] != SEPARATOR_WIN )
+   {
+      name += SEPARATOR;
+   }
+   return name;
+}
+
+/**
+ * \brief   Get the (directory) path from a full path file name
+ * @param   fullName file/directory name to extract Path from
+ */
+std::string Util::GetPath(std::string const &fullName)
+{
+   std::string res = fullName;
+   int pos1 = res.rfind("/");
+   int pos2 = res.rfind("\\");
+   if ( pos1 > pos2 )
+   {
+      res.resize(pos1);
+   }
+   else
+   {
+      res.resize(pos2);
+   }
+
+   return res;
+}
+
+/**
+ * \brief   Get the (last) name of a full path file name
+ * @param   fullName file/directory name to extract end name from
+ */
+std::string Util::GetName(std::string const &fullName)
+{   
+  std::string filename = fullName;
+
+  std::string::size_type slash_pos = filename.rfind("/");
+  std::string::size_type backslash_pos = filename.rfind("\\");
+  slash_pos = slash_pos > backslash_pos ? slash_pos : backslash_pos;
+  if (slash_pos != std::string::npos )
+    {
+    return filename.substr(slash_pos + 1);
+    }
+  else
+    {
+    return filename;
+    }
+} 
+
+/**
+ * \brief   Get the current date of the system in a dicom string
+ */
+std::string Util::GetCurrentDate()
+{
+    char tmp[512];
+    time_t tloc;
+    time (&tloc);    
+    strftime(tmp,512,"%Y%m%d", localtime(&tloc) );
+    return tmp;
+}
+
+/**
+ * \brief   Get the current time of the system in a dicom string
+ */
+std::string Util::GetCurrentTime()
+{
+    char tmp[512];
+    time_t tloc;
+    time (&tloc);
+    strftime(tmp,512,"%H%M%S", localtime(&tloc) );
+    return tmp;  
+}
+
+/**
+ * \brief  Get both the date and time at the same time to avoid problem 
+ * around midnight where the two calls could be before and after midnight
+ */
+std::string Util::GetCurrentDateTime()
+{
+   char tmp[40];
+   long milliseconds;
+   time_t timep;
+  
+   // We need implementation specific functions to obtain millisecond precision
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__)
+   struct timeb tb;
+   ::ftime(&tb);
+   timep = tb.time;
+   milliseconds = tb.millitm;
+#else
+   struct timeval tv;
+   gettimeofday (&tv, NULL);
+   timep = tv.tv_sec;
+   // Compute milliseconds from microseconds.
+   milliseconds = tv.tv_usec / 1000;
+#endif
+   // Obtain the time of day, and convert it to a tm struct.
+   struct tm *ptm = localtime (&timep);
+   // Format the date and time, down to a single second.
+   strftime (tmp, sizeof (tmp), "%Y%m%d%H%M%S", ptm);
+
+   // Add milliseconds
+   // Don't use Util::Format to accelerate execution of code
+   char tmpAll[80];
+   sprintf(tmpAll,"%s%03ld",tmp,milliseconds);
+
+   return tmpAll;
+}
+
+unsigned int Util::GetCurrentThreadID()
+{
+// FIXME the implementation is far from complete
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__)
+  return (unsigned int)GetCurrentThreadId();
+#else
+#ifdef __linux__
+   return 0;
+   // Doesn't work on fedora, but is in the man page...
+   //return (unsigned int)gettid();
+#else
+#ifdef __sun
+   return (unsigned int)thr_self();
+#else
+   //default implementation
+   return 0;
+#endif // __sun
+#endif // __linux__
+#endif // Win32
+}
+
+unsigned int Util::GetCurrentProcessID()
+{
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__)
+  // NOTE: There is also a _getpid()...
+  return (unsigned int)GetCurrentProcessId();
+#else
+  // get process identification, POSIX
+  return (unsigned int)getpid();
+#endif
+}
+
+/**
+ * \brief   tells us whether the processor we are working with is BigEndian or not
+ */
+bool Util::IsCurrentProcessorBigEndian()
+{
+#if defined(GDCM_WORDS_BIGENDIAN)
+   return true;
+#else
+   return false;
+#endif
+}
+
+/**
+ * \brief Create a /DICOM/ string:
+ * It should a of even length (no odd length ever)
+ * It can contain as many (if you are reading this from your
+ * editor the following character is backslash followed by zero
+ * that needed to be escaped with an extra backslash for doxygen) \\0
+ * as you want.
+ */
+std::string Util::DicomString(const char *s, size_t l)
+{
+   std::string r(s, s+l);
+   gdcmAssertMacro( !(r.size() % 2) ); // == basically 'l' is even
+   return r;
+}
+
+/**
+ * \brief Create a /DICOM/ string:
+ * It should a of even length (no odd length ever)
+ * It can contain as many (if you are reading this from your
+ * editor the following character is backslash followed by zero
+ * that needed to be escaped with an extra backslash for doxygen) \\0
+ * as you want.
+ * This function is similar to DicomString(const char*), 
+ * except it doesn't take a length. 
+ * It only pad with a null character if length is odd
+ */
+std::string Util::DicomString(const char *s)
+{
+   size_t l = strlen(s);
+   if ( l%2 )
+   {
+      l++;
+   }
+   std::string r(s, s+l);
+   gdcmAssertMacro( !(r.size() % 2) );
+   return r;
+}
+
+/**
+ * \brief Safely check the equality of two Dicom String:
+ *        - Both strings should be of even length
+ *        - We allow padding of even length string by either
+ *          a null character of a space
+ */
+bool Util::DicomStringEqual(const std::string &s1, const char *s2)
+{
+  // s2 is the string from the DICOM reference e.g. : 'MONOCHROME1'
+  std::string s1_even = s1; //Never change input parameter
+  std::string s2_even = DicomString( s2 );
+  if ( s1_even[s1_even.size()-1] == ' ' )
+  {
+    s1_even[s1_even.size()-1] = '\0'; //replace space character by null
+  }
+  return s1_even == s2_even;
+}
+
+/**
+ * \brief Safely compare two Dicom String:
+ *        - Both strings should be of even length
+ *        - We allow padding of even length string by either
+ *          a null character of a space
+ */
+bool Util::CompareDicomString(const std::string &s1, const char *s2, int op)
+{
+  // s2 is the string from the DICOM reference e.g. : 'MONOCHROME1'
+  std::string s1_even = s1; //Never change input parameter
+  std::string s2_even = DicomString( s2 );
+  if ( s1_even[s1_even.size()-1] == ' ' )
+  {
+    s1_even[s1_even.size()-1] = '\0'; //replace space character by null
+  }
+  switch (op)
+  {
+     case GDCM_EQUAL :
+        return s1_even == s2_even;
+     case GDCM_DIFFERENT :  
+        return s1_even != s2_even;
+     case GDCM_GREATER :  
+        return s1_even >  s2_even;  
+     case GDCM_GREATEROREQUAL :  
+        return s1_even >= s2_even;
+     case GDCM_LESS :
+        return s1_even <  s2_even;
+     case GDCM_LESSOREQUAL :
+        return s1_even <= s2_even;
+     default :
+        gdcmDebugMacro(" Wrong operator : " << op);
+        return false;
+  }
+}
+
+#ifdef _WIN32
+   typedef BOOL(WINAPI * pSnmpExtensionInit) (
+           IN DWORD dwTimeZeroReference,
+           OUT HANDLE * hPollForTrapEvent,
+           OUT AsnObjectIdentifier * supportedView);
+
+   typedef BOOL(WINAPI * pSnmpExtensionTrap) (
+           OUT AsnObjectIdentifier * enterprise,
+           OUT AsnInteger * genericTrap,
+           OUT AsnInteger * specificTrap,
+           OUT AsnTimeticks * timeStamp,
+           OUT RFC1157VarBindList * variableBindings);
+
+   typedef BOOL(WINAPI * pSnmpExtensionQuery) (
+           IN BYTE requestType,
+           IN OUT RFC1157VarBindList * variableBindings,
+           OUT AsnInteger * errorStatus,
+           OUT AsnInteger * errorIndex);
+
+   typedef BOOL(WINAPI * pSnmpExtensionInitEx) (
+           OUT AsnObjectIdentifier * supportedView);
+#endif //_WIN32
+
+#ifdef __sgi
+static int SGIGetMacAddress(unsigned char *addr)
+{
+  FILE *f = popen("/etc/nvram eaddr","r");
+  if(f == 0)
+    {
+    return -1;
+    }
+  unsigned int x[6];
+  if(fscanf(f,"%02x:%02x:%02x:%02x:%02x:%02x",
+            x,x+1,x+2,x+3,x+4,x+5) != 6)
+    {
+    pclose(f);
+    return -1;
+    }
+  for(unsigned int i = 0; i < 6; i++)
+    {
+    addr[i] = static_cast<unsigned char>(x[i]);
+    }
+  return 0;
+}
+#endif
+
+/// \brief gets current M.A.C adress (for internal use only)
+int GetMacAddrSys ( unsigned char *addr );
+int GetMacAddrSys ( unsigned char *addr )
+{
+#ifdef _WIN32
+   WSADATA WinsockData;
+   if ( (WSAStartup(MAKEWORD(2, 0), &WinsockData)) != 0 ) 
+   {
+      std::cerr << "in Get MAC Adress (internal) : This program requires Winsock 2.x!" 
+             << std::endl;
+      return -1;
+   }
+
+   HANDLE PollForTrapEvent;
+   AsnObjectIdentifier SupportedView;
+   UINT OID_ifEntryType[]  = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 3 };
+   UINT OID_ifEntryNum[]   = { 1, 3, 6, 1, 2, 1, 2, 1 };
+   UINT OID_ipMACEntAddr[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 6 };
+   AsnObjectIdentifier MIB_ifMACEntAddr = {
+       sizeof(OID_ipMACEntAddr) / sizeof(UINT), OID_ipMACEntAddr };
+   AsnObjectIdentifier MIB_ifEntryType = {
+       sizeof(OID_ifEntryType) / sizeof(UINT), OID_ifEntryType };
+   AsnObjectIdentifier MIB_ifEntryNum = {
+       sizeof(OID_ifEntryNum) / sizeof(UINT), OID_ifEntryNum };
+   RFC1157VarBindList varBindList;
+   RFC1157VarBind varBind[2];
+   AsnInteger errorStatus;
+   AsnInteger errorIndex;
+   AsnObjectIdentifier MIB_NULL = { 0, 0 };
+   int ret;
+   int dtmp;
+   int j = 0;
+
+   // Load the SNMP dll and get the addresses of the functions necessary
+   HINSTANCE m_hInst = LoadLibrary("inetmib1.dll");
+   if (m_hInst < (HINSTANCE) HINSTANCE_ERROR)
+   {
+      return -1;
+   }
+   pSnmpExtensionInit m_Init =
+       (pSnmpExtensionInit) GetProcAddress(m_hInst, "SnmpExtensionInit");
+   pSnmpExtensionQuery m_Query =
+       (pSnmpExtensionQuery) GetProcAddress(m_hInst, "SnmpExtensionQuery");
+   m_Init(GetTickCount(), &PollForTrapEvent, &SupportedView);
+
+   /* Initialize the variable list to be retrieved by m_Query */
+   varBindList.list = varBind;
+   varBind[0].name = MIB_NULL;
+   varBind[1].name = MIB_NULL;
+
+   // Copy in the OID to find the number of entries in the
+   // Inteface table
+   varBindList.len = 1;        // Only retrieving one item
+   SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryNum);
+   m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus,
+                 &errorIndex);
+//   printf("# of adapters in this system : %i\n",
+//          varBind[0].value.asnValue.number);
+   varBindList.len = 2;
+
+   // Copy in the OID of ifType, the type of interface
+   SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryType);
+
+   // Copy in the OID of ifPhysAddress, the address
+   SNMP_oidcpy(&varBind[1].name, &MIB_ifMACEntAddr);
+
+   do
+   {
+      // Submit the query.  Responses will be loaded into varBindList.
+      // We can expect this call to succeed a # of times corresponding
+      // to the # of adapters reported to be in the system
+      ret = m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus,
+                    &errorIndex); 
+      if (!ret)
+      {
+         ret = 1;
+      }
+      else
+      {
+         // Confirm that the proper type has been returned
+         ret = SNMP_oidncmp(&varBind[0].name, &MIB_ifEntryType,
+                            MIB_ifEntryType.idLength);
+      }
+      if (!ret)
+      {
+         j++;
+         dtmp = varBind[0].value.asnValue.number;
+
+         // Type 6 describes ethernet interfaces
+         if (dtmp == 6)
+         {
+            // Confirm that we have an address here
+            ret = SNMP_oidncmp(&varBind[1].name, &MIB_ifMACEntAddr,
+                               MIB_ifMACEntAddr.idLength);
+            if ( !ret && varBind[1].value.asnValue.address.stream != NULL )
+            {
+               if ( (varBind[1].value.asnValue.address.stream[0] == 0x44)
+                 && (varBind[1].value.asnValue.address.stream[1] == 0x45)
+                 && (varBind[1].value.asnValue.address.stream[2] == 0x53)
+                 && (varBind[1].value.asnValue.address.stream[3] == 0x54)
+                 && (varBind[1].value.asnValue.address.stream[4] == 0x00) )
+               {
+                   // Ignore all dial-up networking adapters
+                   std::cerr << "in Get MAC Adress (internal) : Interface #" 
+                             << j << " is a DUN adapter\n";
+                   continue;
+               }
+               if ( (varBind[1].value.asnValue.address.stream[0] == 0x00)
+                 && (varBind[1].value.asnValue.address.stream[1] == 0x00)
+                 && (varBind[1].value.asnValue.address.stream[2] == 0x00)
+                 && (varBind[1].value.asnValue.address.stream[3] == 0x00)
+                 && (varBind[1].value.asnValue.address.stream[4] == 0x00)
+                 && (varBind[1].value.asnValue.address.stream[5] == 0x00) )
+               {
+                  // Ignore NULL addresses returned by other network
+                  // interfaces
+                  std::cerr << "in Get MAC Adress (internal) :  Interface #" 
+                            << j << " is a NULL address\n";
+                  continue;
+               }
+               memcpy( addr, varBind[1].value.asnValue.address.stream, 6);
+            }
+         }
+      }
+   } while (!ret);
+
+   // Free the bindings
+   SNMP_FreeVarBind(&varBind[0]);
+   SNMP_FreeVarBind(&varBind[1]);
+   return 0;
+#endif //Win32 version
+
+#if defined(__sgi)
+   return SGIGetMacAddress(addr);
+#endif // __sgi
+
+
+// implementation for POSIX system
+#if defined(CMAKE_HAVE_NET_IF_ARP_H) && defined(__sun)
+   //The POSIX version is broken anyway on Solaris, plus would require full
+   //root power
+   struct  arpreq          parpreq;
+   struct  sockaddr_in     *psa;
+   struct  hostent         *phost;
+   char                    hostname[MAXHOSTNAMELEN];
+   char                    **paddrs;
+   int                     sock, status=0;
+
+   if (gethostname(hostname,  MAXHOSTNAMELEN) != 0 )
+   {
+      perror("in Get MAC Adress (internal) : gethostname");
+      return -1;
+   }
+   phost = gethostbyname(hostname);
+   paddrs = phost->h_addr_list;
+
+   sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+   if (sock == -1 )
+   {
+      perror("in Get MAC Adress (internal) : sock");
+      return -1;
+   }
+   memset(&parpreq, 0, sizeof(struct arpreq));
+   psa = (struct sockaddr_in *) &parpreq.arp_pa;
+
+   memset(psa, 0, sizeof(struct sockaddr_in));
+   psa->sin_family = AF_INET;
+   memcpy(&psa->sin_addr, *paddrs, sizeof(struct in_addr));
+
+   status = ioctl(sock, SIOCGARP, &parpreq);
+   if (status == -1 )
+   {
+      perror("in Get MAC Adress (internal) : SIOCGARP");
+      return -1;
+   }
+   memcpy(addr, parpreq.arp_ha.sa_data, 6);
+
+   return 0;
+#else
+#ifdef CMAKE_HAVE_NET_IF_H
+   int       sd;
+   struct ifreq    ifr, *ifrp;
+   struct ifconf    ifc;
+   char buf[1024];
+   int      n, i;
+   unsigned char    *a;
+#if defined(AF_LINK) && (!defined(SIOCGIFHWADDR) && !defined(SIOCGENADDR))
+   struct sockaddr_dl *sdlp;
+#endif
+
+//
+// BSD 4.4 defines the size of an ifreq to be
+// max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
+// However, under earlier systems, sa_len isn't present, so the size is 
+// just sizeof(struct ifreq)
+// We should investigate the use of SIZEOF_ADDR_IFREQ
+//
+#ifdef HAVE_SA_LEN
+   #ifndef max
+      #define max(a,b) ((a) > (b) ? (a) : (b))
+   #endif
+   #define ifreq_size(i) max(sizeof(struct ifreq),\
+        sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
+#else
+   #define ifreq_size(i) sizeof(struct ifreq)
+#endif // HAVE_SA_LEN
+
+   if ( (sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0 )
+   {
+      return -1;
+   }
+   memset(buf, 0, sizeof(buf));
+   ifc.ifc_len = sizeof(buf);
+   ifc.ifc_buf = buf;
+   if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0)
+   {
+      close(sd);
+      return -1;
+   }
+   n = ifc.ifc_len;
+   for (i = 0; i < n; i+= ifreq_size(*ifrp) )
+   {
+      ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
+      strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
+#ifdef SIOCGIFHWADDR
+      if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
+         continue;
+      a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
+#else
+#ifdef SIOCGENADDR
+      // In theory this call should also work on Sun Solaris, but apparently
+      // SIOCGENADDR is not implemented properly thus the call 
+      // ioctl(sd, SIOCGENADDR, &ifr) always returns errno=2 
+      // (No such file or directory)
+      // Furthermore the DLAPI seems to require full root access
+      if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
+         continue;
+      a = (unsigned char *) ifr.ifr_enaddr;
+#else
+#ifdef AF_LINK
+      sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
+      if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
+         continue;
+      a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
+#else
+      perror("in Get MAC Adress (internal) : No way to access hardware");
+      close(sd);
+      return -1;
+#endif // AF_LINK
+#endif // SIOCGENADDR
+#endif // SIOCGIFHWADDR
+      if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) continue;
+
+      if (addr) 
+      {
+         memcpy(addr, a, 6);
+         close(sd);
+         return 0;
+      }
+   }
+   close(sd);
+#endif
+   // Not implemented platforms (or no cable !)
+   perror("in Get MAC Adress (internal) : There was a configuration problem (or no cable !) on your plateform");
+   memset(addr,0,6);
+   return -1;
+#endif //__sun
+}
+
+/**
+ * \brief Mini function to return the last digit from a number express in base 256
+ *        pre condition data contain an array of 6 unsigned char
+ *        post condition carry contain the last digit
+ */
+inline int getlastdigit(unsigned char *data)
+{
+  int extended, carry = 0;
+  for(int i=0;i<6;i++)
+    {
+    extended = (carry << 8) + data[i];
+    data[i] = extended / 10;
+    carry = extended % 10;
+    }
+  return carry;
+}
+
+/**
+ * \brief Encode the mac address on a fixed length string of 15 characters.
+ * we save space this way.
+ */
+std::string Util::GetMACAddress()
+{
+   // This code is the result of a long internet search to find something
+   // as compact as possible (not OS independant). We only have to separate
+   // 3 OS: Win32, SunOS and 'real' POSIX
+   // http://groups-beta.google.com/group/comp.unix.solaris/msg/ad36929d783d63be
+   // http://bdn.borland.com/article/0,1410,26040,00.html
+   unsigned char addr[6];
+
+   int stat = GetMacAddrSys(addr);
+   if (stat == 0)
+   {
+      // We need to convert a 6 digit number from base 256 to base 10, using integer
+      // would requires a 48bits one. To avoid this we have to reimplement the div + modulo 
+      // with string only
+      bool zero = false;
+      int res;
+      std::string sres;
+      while(!zero)
+      {
+         res = getlastdigit(addr);
+         sres.insert(sres.begin(), '0' + res);
+         zero = (addr[0] == 0) && (addr[1] == 0) && (addr[2] == 0) 
+             && (addr[3] == 0) && (addr[4] == 0) && (addr[5] == 0);
+      }
+
+      return sres;
+   }
+   else
+   {
+      gdcmWarningMacro("Problem in finding the MAC Address");
+      return "";
+   }
+}
+
+/**
+ * \brief Creates a new UID. As stipulated in the DICOM ref
+ *        each time a DICOM image is created it should have 
+ *        a unique identifier (URI)
+ * @param root is the DICOM prefix assigned by IOS group
+ */
+std::string Util::CreateUniqueUID(const std::string &root)
+{
+   std::string prefix;
+   std::string append;
+   if ( root.empty() )
+   {
+      // gdcm UID prefix, as supplied by http://www.medicalconnections.co.uk
+      prefix = RootUID; 
+   }
+   else
+   {
+      prefix = root;
+   }
+
+   // A root was specified use it to forge our new UID:
+   append += ".";
+   //append += Util::GetMACAddress(); // to save CPU time
+   append += Util::GDCM_MAC_ADRESS;
+   append += ".";
+   append += Util::GetCurrentDateTime();
+
+   //Also add a mini random number just in case:
+   char tmp[10];
+   int r = (int) (100.0*rand()/RAND_MAX);
+   // Don't use Util::Format to accelerate the execution
+   sprintf(tmp,"%02d", r);
+   append += tmp;
+
+   // If append is too long we need to rehash it
+   if ( (prefix + append).size() > 64 )
+   {
+      gdcmErrorMacro( "Size of UID is too long." );
+      // we need a hash function to truncate this number
+      // if only md5 was cross plateform
+      // MD5(append);
+   }
+
+   return prefix + append;
+}
+
+void Util::SetRootUID(const std::string &root)
+{
+   if ( root.empty() )
+      RootUID = GDCM_UID;
+   else
+      RootUID = root;
+}
+
+const std::string &Util::GetRootUID()
+{
+   return RootUID;
+}
+
+//-------------------------------------------------------------------------
+/**
+ * \brief binary_write binary_write
+ * @param os ostream to write to 
+ * @param val 16 bits value to write
+ */ 
+std::ostream &binary_write(std::ostream &os, const uint16_t &val)
+{
+#if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)
+   uint16_t swap;
+   swap = ( val << 8 | val >> 8 );
+
+   return os.write(reinterpret_cast<const char*>(&swap), 2);
+#else
+   return os.write(reinterpret_cast<const char*>(&val), 2);
+#endif //GDCM_WORDS_BIGENDIAN
+}
+
+/**
+ * \brief binary_write binary_write
+ * @param os ostream to write to
+ * @param val 32 bits value to write
+ */ 
+std::ostream &binary_write(std::ostream &os, const uint32_t &val)
+{
+#if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)
+   uint32_t swap;
+   swap = (  (val<<24)               | ((val<<8)  & 0x00ff0000) | 
+            ((val>>8)  & 0x0000ff00) |  (val>>24)               );
+   return os.write(reinterpret_cast<const char*>(&swap), 4);
+#else
+   return os.write(reinterpret_cast<const char*>(&val), 4);
+#endif //GDCM_WORDS_BIGENDIAN
+}
+
+/**
+ * \brief binary_write binary_write
+ * @param os ostream to write to
+ * @param val double (64 bits) value to write
+ */ 
+std::ostream &binary_write(std::ostream &os, const double &val)
+{
+#if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)    
+   double swap = val;
+   
+   char *beg = (char *)&swap;
+   char *end = beg + 7;
+   char t;
+   for (unsigned int i = 0; i<7; i++)
+   {
+      t    = *beg;
+      *beg = *end;
+      *end = t;
+      beg++,
+      end--;  
+   }  
+   return os.write(reinterpret_cast<const char*>(&swap), 8);
+#else
+   return os.write(reinterpret_cast<const char*>(&val), 8);
+#endif //GDCM_WORDS_BIGENDIAN
+}
+
+/**
+ * \brief  binary_write binary_write
+ * @param os ostream to write to
+ * @param val 8 bits characters aray to write
+ */ 
+std::ostream &binary_write(std::ostream &os, const char *val)
+{
+   return os.write(val, strlen(val));
+}
+
+/**
+ * \brief  binary_write binary_write
+ * @param os ostream to write to
+ * @param val std::string value to write
+ */ 
+std::ostream &binary_write(std::ostream &os, std::string const &val)
+{
+   return os.write(val.c_str(), val.size());
+}
+
+/**
+ * \brief  binary_write binary_write
+ * @param os ostream to write to
+ * @param val 8 bits 'characters' aray to write
+ * @param len length of the 'value' to be written
+ */ 
+std::ostream &binary_write(std::ostream &os, const uint8_t *val, size_t len)
+{
+   // We are writting sizeof(char) thus no need to swap bytes
+   return os.write(reinterpret_cast<const char*>(val), len);
+}
+
+/**
+ * \brief  binary_write binary_write
+ * @param os ostream to write to
+ * @param val 16 bits words aray to write
+ * @param len length (in bytes) of the 'value' to be written 
+ */ 
+std::ostream &binary_write(std::ostream &os, const uint16_t *val, size_t len)
+{
+// This is tricky since we are writting two bytes buffer. 
+// Be carefull with little endian vs big endian. 
+// Also this other trick is to allocate a small (efficient) buffer that store
+// intermediate result before writting it.
+#if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)
+   const int BUFFER_SIZE = 4096;
+   static char buffer[BUFFER_SIZE];
+   uint16_t *binArea16 = (uint16_t*)val; //for the const
+ 
+   // how many BUFFER_SIZE long pieces in binArea ?
+   int nbPieces = len/BUFFER_SIZE; //(16 bits = 2 Bytes)
+   int remainingSize = len%BUFFER_SIZE;
+
+   for (int j=0;j<nbPieces;j++)
+   {
+      uint16_t *pbuffer  = (uint16_t*)buffer; //reinitialize pbuffer
+      for (int i = 0; i < BUFFER_SIZE/2; i++)
+      {
+         *pbuffer = *binArea16 >> 8 | *binArea16 << 8;
+         pbuffer++;
+         binArea16++;
+      }
+      os.write ( buffer, BUFFER_SIZE );
+   }
+   if ( remainingSize > 0)
+   {
+      uint16_t *pbuffer  = (uint16_t*)buffer; //reinitialize pbuffer
+      for (int i = 0; i < remainingSize/2; i++)
+      {
+         *pbuffer = *binArea16 >> 8 | *binArea16 << 8;
+         pbuffer++;
+         binArea16++;
+      }
+      os.write ( buffer, remainingSize );
+   }
+   return os;
+#else
+   return os.write(reinterpret_cast<const char*>(val), len);
+#endif
+}
+
+//-------------------------------------------------------------------------
+// Protected
+
+//-------------------------------------------------------------------------
+// Private
+/**
+ * \brief   Return the IP adress of the machine writting the DICOM image
+ */
+std::string Util::GetIPAddress()
+{
+   // This is a rip from 
+   // http://www.codeguru.com/Cpp/I-N/internet/network/article.php/c3445/
+#ifndef HOST_NAME_MAX
+   // SUSv2 guarantees that `Host names are limited to 255 bytes'.
+   // POSIX 1003.1-2001 guarantees that `Host names (not including the
+   // terminating NUL) are limited to HOST_NAME_MAX bytes'.
+#define HOST_NAME_MAX 255
+   // In this case we should maybe check the string was not truncated.
+   // But I don't known how to check that...
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__)
+   // with WinSock DLL we need to initialize the WinSock before using gethostname
+   WORD wVersionRequested = MAKEWORD(1,0);
+   WSADATA WSAData;
+   int err = WSAStartup(wVersionRequested,&WSAData);
+   if (err != 0)
+   {
+      // Tell the user that we could not find a usable
+      // WinSock DLL.
+      WSACleanup();
+      return "127.0.0.1";
+   }
+#endif
+  
+#endif //HOST_NAME_MAX
+
+   std::string str;
+   char szHostName[HOST_NAME_MAX+1];
+   int r = gethostname(szHostName, HOST_NAME_MAX);
+ 
+   if ( r == 0 )
+   {
+      // Get host adresses
+      struct hostent *pHost = gethostbyname(szHostName);
+ 
+      for( int i = 0; pHost!= NULL && pHost->h_addr_list[i]!= NULL; i++ )
+      {
+         for( int j = 0; j<pHost->h_length; j++ )
+         {
+            if ( j > 0 ) str += ".";
+ 
+            str += Util::Format("%u", 
+                (unsigned int)((unsigned char*)pHost->h_addr_list[i])[j]);
+         }
+         // str now contains one local IP address 
+ 
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__)
+   WSACleanup();
+#endif
+
+      }
+   }
+   // If an error occur r == -1
+   // Most of the time it will return 127.0.0.1...
+   return str;
+}
+
+//-------------------------------------------------------------------------
+} // end namespace gdcm
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmUtil.h b/Utilities/ITK/Utilities/gdcm/src/gdcmUtil.h
new file mode 100644
index 0000000000000000000000000000000000000000..fbf51191f35b59e4abfe3df7df2f8698cd7befe4
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmUtil.h
@@ -0,0 +1,98 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.8 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMUTIL_H
+#define GDCMUTIL_H
+
+#include "gdcmCommon.h"
+#include <vector>
+#include <string>
+
+namespace gdcm 
+{
+/**
+ * \brief    Here are some utility functions, belonging to the gdcm::Util class,
+ *           dealing with strings, file names... that can be called
+ *           from anywhere by whomsoever they can help.
+ */
+
+//-----------------------------------------------------------------------------
+
+class GDCM_EXPORT Util
+{
+public:
+   static std::string Format(const char *format, ...);
+   static void        Tokenize (const std::string &str,
+                                std::vector<std::string> &tokens,
+                                const std::string &delimiters = " ");
+   static int         CountSubstring (const std::string &str,
+                                      const std::string &subStr);
+
+   static std::string CreateCleanString(std::string const &s);
+   static std::string CreateCleanString(uint8_t *s, int l);
+   static bool IsCleanString(std::string const &s);
+   static bool IsCleanArea(uint8_t *s, int l);
+   static std::string NormalizePath(std::string const &name);
+   static std::string GetPath(std::string const &fullName);
+   static std::string GetName(std::string const &fullName);
+   static std::string GetCurrentDate();
+   static std::string GetCurrentTime();
+   static std::string GetCurrentDateTime();
+   /// Provides a simple static GetVersion() function
+   static std::string GetVersion() 
+                      { return GDCM_VERSION;}
+   static unsigned int GetCurrentThreadID();
+   static unsigned int GetCurrentProcessID();
+   static bool         IsCurrentProcessorBigEndian();
+
+   static std::string DicomString(const char *s, size_t l);
+   static std::string DicomString(const char *s);
+   static bool        DicomStringEqual(const std::string &s1, const char *s2);
+   static bool        CompareDicomString(const std::string &s1, 
+                                         const char *s2, int op);
+   static std::string GetMACAddress();
+
+   static std::string CreateUniqueUID(const std::string &root = "");
+   static void SetRootUID(const std::string &root = "");
+   static const std::string &GetRootUID();
+
+   static const uint8_t *GetFileMetaInformationVersion() 
+                     { return FileMetaInformationVersion;}
+   static void SetFileMetaInformationVersion( uint16_t fmiv )
+                     { FileMetaInformationVersion = (uint8_t *)&fmiv; }
+
+private:
+   static std::string GetIPAddress(); //Do not expose this method
+
+   static std::string RootUID;
+   static const std::string GDCM_UID;
+   static uint8_t *FileMetaInformationVersion;
+   static const uint16_t FMIV;
+   static std::string GDCM_MAC_ADRESS;
+};
+
+GDCM_EXPORT std::ostream &binary_write(std::ostream &os, const uint16_t &val);
+GDCM_EXPORT std::ostream &binary_write(std::ostream &os, const uint32_t &val);
+GDCM_EXPORT std::ostream &binary_write(std::ostream &os, const double &val);
+GDCM_EXPORT std::ostream &binary_write(std::ostream &os, const char *val);
+GDCM_EXPORT std::ostream &binary_write(std::ostream &os, std::string const &val);
+GDCM_EXPORT std::ostream &binary_write(std::ostream &os, const uint8_t *val, size_t len);
+GDCM_EXPORT std::ostream &binary_write(std::ostream &os, const uint16_t *val, size_t len);
+} // end namespace gdcm
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmVR.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmVR.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..038e1f40b8836b0f847c6777e37974510ef8efb5
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmVR.cxx
@@ -0,0 +1,166 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmVR.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.6 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmVR.h"
+#include "gdcmUtil.h"
+#include "gdcmDictSet.h"
+#include "gdcmDebug.h"
+
+#include <fstream>
+#include <iostream>
+#include <string.h>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/// \brief auto generated function, to fill up the 'Value Representation'
+///        Dictionnary, if relevant file is not found on user's disk
+void FillDefaultVRDict(VRHT &vr);
+
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief Constructor
+ */
+VR::VR() 
+{
+   std::string filename = DictSet::BuildDictPath() + DICT_VR;
+   std::ifstream from(filename.c_str());
+   if ( !from )
+   {
+      gdcmWarningMacro("Can't open dictionary " << filename.c_str());
+      FillDefaultVRDict(vr);
+   }
+   else
+   {
+      char buff[1024];
+      VRKey key;
+      VRAtr name;
+   
+      while (!from.eof()) 
+      {
+         from >> std::ws;
+         from.getline(buff, 1024, ' ');
+         if( strcmp(buff,"") == 0)
+            continue;
+
+         key = buff;
+         from >> std::ws;
+         from.getline(buff, 1024, ';');
+         name = buff;
+   
+         from >> std::ws;
+         from.getline(buff, 1024, '\n');
+   
+         vr[key] = name;
+      }
+      from.close();
+   }
+}
+
+/**
+ * \brief Destructor
+ */
+VR::~VR()
+{
+   vr.clear();
+}
+
+//-----------------------------------------------------------------------------
+// Public
+
+/**
+ * \brief   Simple predicate that checks whether the given argument
+ *          corresponds to the Value Representation of a \ref BinEntry .
+ * @param   tested value representation to check for.
+ */
+bool VR::IsVROfBinaryRepresentable(VRKey const &tested)
+{
+   if ( IsVROfStringRepresentable(tested) )
+      return false;
+
+   if ( IsVROfSequence(tested) )
+      return false;
+
+   return true;
+}
+
+/**
+ * \brief   Simple predicate that checks whether the given argument
+ *          corresponds to the Value Representation of a \ref ValEntry
+ *          but NOT a \ref BinEntry.
+ * @param   tested value representation to be checked.
+ */
+bool VR::IsVROfStringRepresentable(VRKey const &tested)
+{
+
+   return tested == "AE" ||
+          tested == "AS" ||
+          tested == "CS" ||
+          tested == "DA" ||
+          tested == "DS" ||
+          tested == "FL" ||
+          tested == "FD" || 
+          tested == "IS" || 
+          tested == "LO" ||
+          tested == "LT" ||
+          tested == "PN" ||
+          tested == "SH" ||
+          tested == "SL" ||
+          tested == "SS" ||
+          tested == "ST" ||
+          tested == "TM" ||
+          tested == "UI" ||
+          tested == "UL" ||
+          tested == "US" ||
+          tested == "UT";
+
+   // Should be quicker
+   // --> will *never* work : any rotten value would be considered as OK !
+/*
+   return tested != "OB" &&
+          tested != "OW" &&
+          tested != "OF" &&
+          tested != "AT" && // Attribute Tag ?!? contain no printable character
+          tested != "UN" && // UN is an actual VR !
+          tested != "SQ" ;
+*/
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Print all 
+ * @param   os The output stream to be written to.
+ */
+void VR::Print(std::ostream &os,std::string const &) 
+{
+   for (VRHT::iterator it = vr.begin(); it != vr.end(); ++it)
+   {
+      os << "VR : " << it->first << " = " << it->second << std::endl;
+   }
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmVR.h b/Utilities/ITK/Utilities/gdcm/src/gdcmVR.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4a68fef7b3aa676e42b199c7a1ca7e6ad382632
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmVR.h
@@ -0,0 +1,68 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmVR.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMVR_H
+#define GDCMVR_H
+
+#include "gdcmCommon.h"
+#include <map>
+#include <string>
+#include <iostream>
+
+namespace gdcm 
+{
+
+//-----------------------------------------------------------------------------
+typedef std::string VRKey;
+typedef std::string VRAtr;
+/// Value Representation Hash Table
+typedef std::map<VRKey, VRAtr> VRHT;
+
+//-----------------------------------------------------------------------------
+/**
+ * \brief Container for dicom Value Representation Hash Table
+ * \note   This is a singleton
+ */
+class GDCM_EXPORT VR 
+{
+public:
+   VR();
+   ~VR();
+
+   void Print(std::ostream &os = std::cout,
+              std::string const &s = "");
+
+   /// \brief   Get the count for an element
+   int Count(VRKey const &key) { return vr.count(key); };
+
+   bool IsVROfBinaryRepresentable(VRKey const &tested);
+   bool IsVROfStringRepresentable(VRKey const &tested);
+
+   /// \brief   Simple predicate that checks whether the given argument
+   ///          corresponds to the Value Representation of a \ref SeqEntry
+   bool IsVROfSequence(VRKey const &tested) { return tested == "SQ"; }
+
+   bool IsValidVR(VRKey const &key) { return vr.find(key) != vr.end(); }
+
+private:
+   VRHT vr;
+};
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmValEntry.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmValEntry.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..221f5b34ecb52025a5fe8d5018c88ac821ec1bb3
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmValEntry.cxx
@@ -0,0 +1,315 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmValEntry.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:58 $
+  Version:   $Revision: 1.8 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmValEntry.h"
+#include "gdcmVR.h"
+#include "gdcmTS.h"
+#include "gdcmGlobal.h"
+#include "gdcmUtil.h"
+#include "gdcmDebug.h"
+#include "gdcmDocument.h"
+
+#include <fstream>
+#include <ctype.h>  // for isdigit
+#include <stdlib.h> // for atoi
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+#define MAX_SIZE_PRINT_ELEMENT_VALUE 0x7fffffff
+uint32_t ValEntry::MaxSizePrintEntry = MAX_SIZE_PRINT_ELEMENT_VALUE;
+//-----------------------------------------------------------------------------
+// Constructor / Destructor
+/**
+ * \brief   Constructor from a given DictEntry
+ * @param   e Pointer to existing dictionary entry
+ */
+ValEntry::ValEntry(DictEntry *e) 
+        : ContentEntry(e)
+{
+}
+
+/**
+ * \brief   Constructor from a given DocEntry
+ * @param   e Pointer to existing Doc entry
+ */
+ValEntry::ValEntry(DocEntry *e)
+        : ContentEntry(e->GetDictEntry())
+{
+   Copy(e);
+}
+
+/**
+ * \brief   Canonical destructor.
+ */
+ValEntry::~ValEntry ()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Public
+/**
+ * \brief   Writes the std::string representable' value of a ValEntry
+ * @param fp already open ofstream pointer
+ * @param filetype type of the file (ACR, ImplicitVR, ExplicitVR, ...)
+ */
+void ValEntry::WriteContent(std::ofstream *fp, FileType filetype)
+{
+   DocEntry::WriteContent(fp, filetype);
+
+   if ( GetGroup() == 0xfffe )
+   {
+      return; //delimitors have NO value
+   }
+
+   const VRKey &vr = GetVR();
+   unsigned int lgth = GetLength();
+   if (vr == "US" || vr == "SS")
+   {
+      // some 'Short integer' fields may be multivaluated
+      // each single value is separated from the next one by '\'
+      // we split the string and write each value as a short int
+      std::vector<std::string> tokens;
+      tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
+      Util::Tokenize (GetValue(), tokens, "\\");
+      for (unsigned int i=0; i<tokens.size();i++)
+      {
+         uint16_t val_uint16 = atoi(tokens[i].c_str());
+         binary_write( *fp, val_uint16);
+      }
+      tokens.clear();
+      return;
+   }
+   if (vr == "UL" || vr == "SL")
+   {
+      // Some 'Integer' fields may be multivaluated (multiple instances 
+      // of integer). But each single integer value is separated from the
+      // next one by '\' (backslash character). Hence we split the string
+      // along the '\' and write each value as an int:
+      std::vector<std::string> tokens;
+      tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
+      Util::Tokenize (GetValue(), tokens, "\\");
+      for (unsigned int i=0; i<tokens.size();i++)
+      {
+         uint32_t val_uint32 = atoi(tokens[i].c_str());
+         binary_write( *fp, val_uint32);
+      }
+      tokens.clear();
+      return;
+   } 
+
+   gdcmAssertMacro( lgth == GetValue().length() );
+   binary_write(*fp, GetValue());
+} 
+
+
+/**
+ * \brief Header Elements too long will not be printed
+ * @param newSize new size
+ */ 
+void ValEntry::SetMaxSizePrintEntry(long newSize) 
+{
+   if ( newSize < 0 )
+   {
+      return;
+   }
+   if ((uint32_t)newSize >= (uint32_t)0xffffffff )
+   {
+      ValEntry::MaxSizePrintEntry = 0xffffffff;
+      return;
+   }
+   ValEntry::MaxSizePrintEntry = newSize;
+}
+
+
+/**
+ * \brief   Sets the std::string representable' value of a ValEntry
+ * @param  val value to set 
+ */
+void ValEntry::SetValue(std::string const &val)
+{
+   // Integers have a special treatement for their length:
+   int l = val.length();
+   if ( l != 0) // To avoid to be cheated by 'zero length' integers
+   {   
+      const VRKey &vr = GetVR();
+      if ( vr == "US" || vr == "SS" )
+      {
+         // for multivaluated items
+         l = (Util::CountSubstring(val, "\\") + 1) * 2;
+         ContentEntry::SetValue(val);
+      }
+      else if ( vr == "UL" || vr == "SL" )
+      {
+         // for multivaluated items
+         l = (Util::CountSubstring(val, "\\") + 1) * 4;;
+         ContentEntry::SetValue(val);
+      }
+      else
+      {
+         std::string finalVal = Util::DicomString( val.c_str() );
+         gdcmAssertMacro( !(finalVal.size() % 2) );
+
+         l = finalVal.length();
+         ContentEntry::SetValue(finalVal);
+      }
+   }
+   else
+   {
+      std::string finalVal = Util::DicomString( val.c_str() );
+      gdcmAssertMacro( !(finalVal.size() % 2) );
+
+      l = finalVal.length();
+      ContentEntry::SetValue(finalVal);
+   }
+
+   SetLength(l);
+}
+
+/**
+ * \brief   Compute the full length of the elementary DataEntry (not only value
+ *          length) depending on the VR.
+ */
+uint32_t ValEntry::ComputeFullLength()
+{
+   return GetFullLength();
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+
+//-----------------------------------------------------------------------------
+// Private
+
+//-----------------------------------------------------------------------------
+// Print
+/**
+ * \brief   Prints the 'std::string representable' value of ValEntry
+ * @param   os ostream we want to print in
+ * @param indent Indentation string to be prepended during printing
+ */
+void ValEntry::Print(std::ostream &os, std::string const &)
+{
+   uint16_t g = GetGroup();
+   uint16_t e = GetElement();
+   VRKey vr   = GetVR();
+   itksys_ios::ostringstream s; 
+   std::string st;
+   std::string d2;
+     
+   os << "V ";
+   DocEntry::Print(os); 
+
+   if (g == 0xfffe) // delimiters have NO value
+   {
+      // just to avoid identing all the remaining code     
+      return;
+   }
+   
+   TS *ts = Global::GetTS();
+    
+   TSAtr v  = GetValue();     
+   d2 = Util::CreateCleanString(v);  // replace non printable characters by '.'            
+   if ( (long)GetLength() <= ValEntry::GetMaxSizePrintEntry()
+    || PrintLevel >= 3
+    || d2.find(GDCM_NOTLOADED) < d2.length() )
+   {
+      s << " [" << d2 << "]";
+   }
+   else
+   {
+      s << " [gdcm::too long for print (" << GetLength() << ") ]";
+   }
+   
+   // Display the UID value (instead of displaying only the rough code)
+   // First 'clean' trailing character (space or zero) 
+   if (g == 0x0002)
+   {
+      // Any more to be displayed ?
+      if ( e == 0x0010 || e == 0x0002 )
+      {
+         if ( v.length() != 0 )  // for brain damaged headers
+         {
+            if ( ! isdigit((unsigned char)v[v.length()-1]) )
+            {
+               v.erase(v.length()-1, 1);
+            }
+         }
+         s << "  ==>\t[" << ts->GetValue(v) << "]";
+      }
+   }
+   else
+   {
+      if (g == 0x0008)
+      {
+         if ( e == 0x0016 || e == 0x1150 )
+         {
+            if ( v.length() != 0 )  // for brain damaged headers
+            {
+               if ( ! isdigit((unsigned char)v[v.length()-1]) )
+               {
+                  v.erase(v.length()-1, 1);
+               }
+            }
+            s << "  ==>\t[" << ts->GetValue(v) << "]";
+         }
+      }
+      else
+      {
+         if (g == 0x0004)
+         {
+            if ( e == 0x1510 || e == 0x1512  )
+            {
+               if ( v.length() != 0 )  // for brain damaged headers  
+               {
+                  if ( ! isdigit((unsigned char)v[v.length()-1]) )
+                  {
+                     v.erase(v.length()-1, 1);  
+                  }
+               }
+              s << "  ==>\t[" << ts->GetValue(v) << "]";
+            }
+         }     
+      }
+   }
+   //if (e == 0x0000) {        // elem 0x0000 --> group length 
+   if ( vr == "UL" || vr == "US" || vr == "SL" || vr == "SS" )
+   {
+      if (v == "4294967295") // to avoid troubles in convertion 
+      {
+         st = "ffffffff";
+      }
+      else
+      {
+         if ( GetLength() != 0 )
+         {
+            st = Util::Format(" x(%x)", atoi(v.c_str()));//FIXME
+         }
+         else
+         {
+            st = " ";
+         }
+      }
+      s << st;
+   }
+   os << s.str();
+}
+
+//-----------------------------------------------------------------------------
+} // end namespace gdcm
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmValEntry.h b/Utilities/ITK/Utilities/gdcm/src/gdcmValEntry.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a12629bb941a020fe6f6ced2cbd5cba3b06ef32
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmValEntry.h
@@ -0,0 +1,83 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmValEntry.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.4 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#ifndef GDCMVALENTRY_H
+#define GDCMVALENTRY_H
+
+#include "gdcmDocEntry.h"
+#include "gdcmContentEntry.h"
+
+#include <iostream>
+
+namespace gdcm 
+{
+//-----------------------------------------------------------------------------
+/**
+ * \brief   Any Dicom Document (File or DicomDir) contains 
+ *           a set of DocEntry  - Dicom entries -
+ *          ValEntry is an elementary DocEntry (i.e. a ContentEntry, 
+ *           as opposed to SeqEntry)
+ *          whose content is 'std::string representable' : characters,
+ *          or integers (loaded in memory as a std::string)
+ *          ValEntry is a specialisation of ContentEntry
+ */
+class GDCM_EXPORT ValEntry  : public ContentEntry
+{
+public:
+
+   // Contructors and Destructor are public.
+   ValEntry(DictEntry *e);
+   ValEntry(DocEntry *d); 
+
+   ~ValEntry();
+
+   // Other accessors are inherited from gdcm::ContentEntry
+
+   void Print(std::ostream &os = std::cout, std::string const &indent = ""); 
+
+   void WriteContent(std::ofstream *fp, FileType filetype); 
+   
+   /// Sets the value (string) of the current Dicom entry.
+   /// The size is updated
+   void SetValue(std::string const &val);
+
+   uint32_t ComputeFullLength();
+
+
+   /// \brief returns the size threshold above which an element value 
+   ///        will NOT be *printed* in order no to polute the screen output
+   static long GetMaxSizePrintEntry() { return ValEntry::MaxSizePrintEntry; }
+
+   static void SetMaxSizePrintEntry(long);
+
+protected:
+   
+private:
+
+   /// \brief Size threshold above which an element val
+   ///        By default, this upper bound is fixed to 64 bytes.
+
+   static uint32_t MaxSizePrintEntry;   
+
+};
+
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
+
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmValidator.cxx b/Utilities/ITK/Utilities/gdcm/src/gdcmValidator.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..566bb795c1fe28a6fff42fe0697841edf25e0464
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmValidator.cxx
@@ -0,0 +1,87 @@
+/*=========================================================================
+                                                                                
+  Program:   gdcm
+  Module:    $RCSfile: gdcmValidator.cxx,v $
+  Language:  C++
+  Date:      $Date: 2006/02/20 15:56:58 $
+  Version:   $Revision: 1.5 $
+                                                                                
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+                                                                                
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+                                                                                
+=========================================================================*/
+
+#include "gdcmValidator.h"
+#include "gdcmElementSet.h"
+#include "gdcmBinEntry.h"
+#include "gdcmValEntry.h"
+#include "gdcmDebug.h" // hidden way to include sstream
+
+namespace gdcm 
+{
+
+Validator::Validator()
+{
+}
+
+Validator::~Validator()
+{
+}
+
+// Function to compare the VM found while parsing d->GetValue()
+// compare to the one from the dictionary
+bool CheckVM(ValEntry *v)
+{
+  const std::string &s = v->GetValue();
+  std::string::size_type n = s.find("\\");
+  if ( n == s.npos ) // none found
+  {
+    n = 0;
+  }
+  n++; // number of '\' + 1 == Value Multiplicity
+
+  unsigned int m;
+  itksys_ios::istringstream is;
+  is.str( v->GetVM());
+  is >> m;
+
+  return n == m;
+}
+
+void Validator::SetInput(ElementSet *input)
+{
+  // berk for now SetInput do two things at the same time
+  gdcm::DocEntry *d=input->GetFirstEntry();
+  while(d)
+  {
+    if ( gdcm::BinEntry *b = dynamic_cast<gdcm::BinEntry*>(d) )
+    {
+//      copyH->InsertBinEntry( b->GetBinArea(),b->GetLength(),
+//        b->GetGroup(),b->GetElement(),
+//        b->GetVR() );
+        (void)b;
+    }
+    else if ( gdcm::ValEntry *v = dynamic_cast<gdcm::ValEntry*>(d) )
+    {   
+      if ( !CheckVM(v) )
+      {
+        std::cout << "This DICOM contains one wrong tag:" << 
+        v->GetValue() << " " <<
+        v->GetGroup() << "," << v->GetElement() << "," <<
+        v->GetVR() << " " << v->GetVM() << " " << v->GetName() << std::endl;
+      }
+    }
+    else
+    {
+      // We skip pb of SQ recursive exploration
+    }
+    d=input->GetNextEntry();
+  }
+}
+
+} // end namespace gdcm
diff --git a/Utilities/ITK/Utilities/gdcm/src/gdcmValidator.h b/Utilities/ITK/Utilities/gdcm/src/gdcmValidator.h
new file mode 100644
index 0000000000000000000000000000000000000000..98ee89db6c6f1246465a5d9bdc3ec2329d9d6488
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/gdcmValidator.h
@@ -0,0 +1,43 @@
+/*=========================================================================
+ 
+  Program:   gdcm
+  Module:    $RCSfile: gdcmValidator.h,v $
+  Language:  C++
+  Date:      $Date: 2006/02/18 12:36:39 $
+  Version:   $Revision: 1.2 $
+ 
+  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
+  l'Image). All rights reserved. See Doc/License.txt or
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
+ 
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+ 
+=========================================================================*/
+
+#ifndef GDCMVALIDATOR_H
+#define GDCMVALIDATOR_H
+
+#include "gdcmBase.h"
+
+namespace gdcm 
+{
+/**
+ * \brief Class to perform some verifications on a gdcm::Document
+ */
+class ElementSet;
+class GDCM_EXPORT Validator : public Base
+{
+public:
+   Validator();
+   ~Validator();
+
+   void SetInput(ElementSet *input);
+
+};
+
+} // end namespace gdcm
+
+//-----------------------------------------------------------------------------
+#endif
diff --git a/Utilities/ITK/Utilities/gdcm/src/jdatadst.cxx b/Utilities/ITK/Utilities/gdcm/src/jdatadst.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..63ae9a171e1faa1db558adbff33bf519a0964e13
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/jdatadst.cxx
@@ -0,0 +1,194 @@
+/*
+ * jdatadst.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains compression data destination routines for the case of
+ * emitting JPEG data to a file (or any stdio stream).  While these routines
+ * are sufficient for most applications, some will want to use a different
+ * destination manager.
+ * IMPORTANT: we assume that fwrite() will correctly transcribe an array of
+ * JOCTETs into 8-bit-wide elements on external storage.  If char is wider
+ * than 8 bits on your machine, you may need to do some tweaking.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+
+
+/* Expanded data destination object for stdio output */
+
+extern "C" {
+  typedef  boolean(*boolean_jpeg_compress_struct)(jpeg_compress_struct*);
+  typedef  void(*void_jpeg_compress_struct)(jpeg_compress_struct*);
+}
+
+typedef struct {
+  struct jpeg_destination_mgr pub; /* public fields */
+
+  std::ostream * outfile; /* target stream */ 
+  JOCTET * buffer;         /* start of buffer */
+//  boolean start_of_file;  /* have we gotten any data yet? */
+
+  size_t frag_length;  //we have to control this one to spec the size of the frag
+  size_t bytes_written;
+} my_destination_mgr;
+
+typedef my_destination_mgr * my_dest_ptr;
+
+#define OUTPUT_BUF_SIZE  4096  /* choose an efficiently fwrite'able size */
+
+
+/*
+ * Initialize destination --- called by jpeg_start_compress
+ * before any data is actually written.
+ */
+
+METHODDEF(void)
+init_destination (j_compress_ptr cinfo)
+{
+  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+  /* Allocate the output buffer --- it will be released when done with image */
+  dest->buffer = (JOCTET *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
+
+  dest->pub.next_output_byte = dest->buffer;
+  dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+
+/*
+ * Empty the output buffer --- called whenever buffer fills up.
+ *
+ * In typical applications, this should write the entire output buffer
+ * (ignoring the current state of next_output_byte & free_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been dumped.
+ *
+ * In applications that need to be able to suspend compression due to output
+ * overrun, a FALSE return indicates that the buffer cannot be emptied now.
+ * In this situation, the compressor will return to its caller (possibly with
+ * an indication that it has not accepted all the supplied scanlines).  The
+ * application should resume compression after it has made more room in the
+ * output buffer.  Note that there are substantial restrictions on the use of
+ * suspension --- see the documentation.
+ *
+ * When suspending, the compressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_output_byte & free_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point will be regenerated after resumption, so do not
+ * write it out when emptying the buffer externally.
+ */
+
+METHODDEF(boolean)
+empty_output_buffer (j_compress_ptr cinfo)
+{
+  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+  if( dest->bytes_written == dest->frag_length )
+    {
+    // Start the I/O suspension simply by returning false here:
+    return FALSE;
+    }
+
+  size_t output_buf_size = OUTPUT_BUF_SIZE;
+  if( (dest->bytes_written + OUTPUT_BUF_SIZE) > dest->frag_length )
+    {
+    output_buf_size = dest->frag_length - dest->bytes_written;
+    }
+  dest->outfile->write((char*)dest->buffer, output_buf_size);
+  size_t nbytes = output_buf_size; //dest->outfile->gcount();
+
+  if( nbytes <= 0 )
+    ERREXIT(cinfo, JERR_FILE_WRITE);
+
+  if( dest->outfile->fail() )
+    ERREXIT(cinfo, JERR_FILE_WRITE);
+
+  dest->pub.next_output_byte = dest->buffer;
+  dest->pub.free_in_buffer = nbytes; //OUTPUT_BUF_SIZE;
+  dest->bytes_written += nbytes;
+
+  return TRUE;
+}
+
+
+/*
+ * Terminate destination --- called by jpeg_finish_compress
+ * after all data has been written.  Usually needs to flush buffer.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+
+METHODDEF(void)
+term_destination (j_compress_ptr cinfo)
+{
+  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+  size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+
+  /* Write any data remaining in the buffer */
+#if 0
+  if (datacount > 0) {
+    if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
+      ERREXIT(cinfo, JERR_FILE_WRITE);
+  }
+  fflush(dest->outfile);
+  /* Make sure we wrote the output file OK */
+  if (ferror(dest->outfile))
+    ERREXIT(cinfo, JERR_FILE_WRITE);
+#else
+  if (datacount > 0) {
+    dest->outfile->write((char*)dest->buffer, datacount);
+    if (dest->outfile->fail())
+      ERREXIT(cinfo, JERR_FILE_WRITE);
+    dest->outfile->flush();
+    /* Make sure we wrote the output file OK */
+    if (dest->outfile->fail())
+      ERREXIT(cinfo, JERR_FILE_WRITE);
+  }
+#endif
+}
+
+
+/*
+ * Prepare for output to a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing compression.
+ */
+
+GLOBAL(void)
+jpeg_stdio_dest (j_compress_ptr cinfo, std::ostream * outfile, size_t frag_length, int flag)
+{
+  my_dest_ptr dest;
+
+  /* The destination object is made permanent so that multiple JPEG images
+   * can be written to the same file without re-executing jpeg_stdio_dest.
+   * This makes it dangerous to use this manager and a different destination
+   * manager serially with the same JPEG object, because their private object
+   * sizes may be different.  Caveat programmer.
+   */
+  if (cinfo->dest == NULL) {  /* first time for this JPEG object? */
+    cinfo->dest = (struct jpeg_destination_mgr *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+          SIZEOF(my_destination_mgr));
+  }
+
+  dest = (my_dest_ptr) cinfo->dest;
+  dest->pub.init_destination = reinterpret_cast<void_jpeg_compress_struct>(init_destination);
+  dest->pub.empty_output_buffer = reinterpret_cast<boolean_jpeg_compress_struct>(empty_output_buffer);
+  dest->pub.term_destination = reinterpret_cast<void_jpeg_compress_struct>(term_destination);
+  dest->outfile = outfile;
+
+  // Need to setup a new buffer, clean bytes_in_buffer and next_input_byte
+  if( flag )
+    {
+    dest->bytes_written = 0;
+    }
+  // only upate the new fragment, valid for both 'flag' value
+  dest->frag_length = frag_length;
+}
diff --git a/Utilities/ITK/Utilities/gdcm/src/jdatasrc.cxx b/Utilities/ITK/Utilities/gdcm/src/jdatasrc.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..bf658ef10b2fc0bab7c07f7ee547ace1450ae594
--- /dev/null
+++ b/Utilities/ITK/Utilities/gdcm/src/jdatasrc.cxx
@@ -0,0 +1,239 @@
+/*
+ * jdatasrc.cxx
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains decompression data source routines for the case of
+ * reading JPEG data from a file (or any stdio stream).  While these routines
+ * are sufficient for most applications, some will want to use a different
+ * source manager.
+ * IMPORTANT: we assume that fread() will correctly transcribe an array of
+ * JOCTETs from 8-bit-wide elements on external storage.  If char is wider
+ * than 8 bits on your machine, you may need to do some tweaking.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+
+/* Expanded data source object for stdio input */
+
+extern "C" {
+  typedef  boolean(*boolean_jpeg_decompress_struct)(jpeg_decompress_struct*);
+  typedef  void(*void_jpeg_decompress_struct)(jpeg_decompress_struct*);
+  typedef  void(*void_jpeg_decompress_struct_long)(jpeg_decompress_struct*,long);
+}
+
+typedef struct {
+  struct jpeg_source_mgr pub;  /* public fields */
+
+  std::istream *infile;  /* source stream */ 
+  JOCTET * buffer;        /* start of buffer */
+  boolean start_of_file;  /* have we gotten any data yet? */
+
+  gdcm::JPEGFragment *frag;
+  size_t bytes_read;
+} my_source_mgr;
+
+typedef my_source_mgr * my_src_ptr;
+
+#define INPUT_BUF_SIZE  4096  /* choose an efficiently fread'able size */
+
+
+/*
+ * Initialize source --- called by jpeg_read_header
+ * before any data is actually read.
+ */
+
+METHODDEF(void)
+init_source (j_decompress_ptr cinfo)
+{
+  my_src_ptr src = (my_src_ptr) cinfo->src;
+
+  /* We reset the empty-input-file flag for each image,
+   * but we don't clear the input buffer.
+   * This is correct behavior for reading a series of images from one source.
+   */
+  src->start_of_file = TRUE;
+}
+
+
+/*
+ * Fill the input buffer --- called whenever buffer is emptied.
+ *
+ * In typical applications, this should read fresh data into the buffer
+ * (ignoring the current state of next_input_byte & bytes_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been reloaded.  It is not necessary to
+ * fill the buffer entirely, only to obtain at least one more byte.
+ *
+ * There is no such thing as an EOF return.  If the end of the file has been
+ * reached, the routine has a choice of ERREXIT() or inserting fake data into
+ * the buffer.  In most cases, generating a warning message and inserting a
+ * fake EOI marker is the best course of action --- this will allow the
+ * decompressor to output however much of the image is there.  However,
+ * the resulting error message is misleading if the real problem is an empty
+ * input file, so we handle that case specially.
+ *
+ * In applications that need to be able to suspend compression due to input
+ * not being available yet, a FALSE return indicates that no more data can be
+ * obtained right now, but more may be forthcoming later.  In this situation,
+ * the decompressor will return to its caller (with an indication of the
+ * number of scanlines it has read, if any).  The application should resume
+ * decompression after it has loaded more data into the input buffer.  Note
+ * that there are substantial restrictions on the use of suspension --- see
+ * the documentation.
+ *
+ * When suspending, the decompressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point must be rescanned after resumption, so move it to
+ * the front of the buffer rather than discarding it.
+ */
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+  my_src_ptr src = (my_src_ptr) cinfo->src;
+
+  if( src->bytes_read == src->frag->GetLength() )
+    {
+    // Start the I/O suspension simply by returning false here:
+    return FALSE;
+    }
+
+  size_t input_buf_size = INPUT_BUF_SIZE;
+  if( (src->bytes_read + INPUT_BUF_SIZE) > src->frag->GetLength() )
+    {
+    input_buf_size = src->frag->GetLength() - src->bytes_read;
+    }
+
+  src->infile->read( (char*)src->buffer, input_buf_size);
+  size_t nbytes = src->infile->gcount();
+
+  if (nbytes <= 0) {
+    if (src->start_of_file)  /* Treat empty input file as fatal error */
+      ERREXIT(cinfo, JERR_INPUT_EMPTY);
+    WARNMS(cinfo, JWRN_JPEG_EOF);
+    /* Insert a fake EOI marker */
+    src->buffer[0] = (JOCTET) 0xFF;
+    src->buffer[1] = (JOCTET) JPEG_EOI;
+    nbytes = 2;
+  }
+
+  src->pub.next_input_byte = src->buffer;
+  src->pub.bytes_in_buffer = nbytes;
+  src->start_of_file = FALSE;
+  src->bytes_read += nbytes;
+
+  return TRUE;
+}
+
+
+/*
+ * Skip data --- used to skip over a potentially large amount of
+ * uninteresting data (such as an APPn marker).
+ *
+ * Writers of suspendable-input applications must note that skip_input_data
+ * is not granted the right to give a suspension return.  If the skip extends
+ * beyond the data currently in the buffer, the buffer can be marked empty so
+ * that the next read will cause a fill_input_buffer call that can suspend.
+ * Arranging for additional bytes to be discarded before reloading the input
+ * buffer is the application writer's problem.
+ */
+
+METHODDEF(void)
+skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+  my_src_ptr src = (my_src_ptr) cinfo->src;
+
+  /* Just a dumb implementation for now.  Could use fseek() except
+   * it doesn't work on pipes.  Not clear that being smart is worth
+   * any trouble anyway --- large skips are infrequent.
+   */
+  if (num_bytes > 0) {
+    while (num_bytes > (long) src->pub.bytes_in_buffer) {
+      num_bytes -= (long) src->pub.bytes_in_buffer;
+      (void) fill_input_buffer(cinfo);
+      /* note we assume that fill_input_buffer will never return FALSE,
+       * so suspension need not be handled.
+       */
+    }
+    src->pub.next_input_byte += (size_t) num_bytes;
+    src->pub.bytes_in_buffer -= (size_t) num_bytes;
+  }
+}
+
+
+/*
+ * An additional method that can be provided by data source modules is the
+ * resync_to_restart method for error recovery in the presence of RST markers.
+ * For the moment, this source module just uses the default resync method
+ * provided by the JPEG library.  That method assumes that no backtracking
+ * is possible.
+ */
+
+
+/*
+ * Terminate source --- called by jpeg_finish_decompress
+ * after all data has been read.  Often a no-op.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+
+METHODDEF(void)
+term_source (j_decompress_ptr cinfo)
+{
+  cinfo=cinfo;
+  /* no work necessary here */
+}
+
+
+/*
+ * Prepare for input from a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing decompression.
+ */
+
+GLOBAL(void)
+jpeg_stdio_src (j_decompress_ptr cinfo, std::istream * infile, gdcm::JPEGFragment *frag, int flag)
+{
+  my_src_ptr src;
+
+  /* The source object and input buffer are made permanent so that a series
+   * of JPEG images can be read from the same file by calling jpeg_stdio_src
+   * only before the first one.  (If we discarded the buffer at the end of
+   * one image, we'd likely lose the start of the next one.)
+   * This makes it unsafe to use this manager and a different source
+   * manager serially with the same JPEG object.  Caveat programmer.
+   */
+  if (cinfo->src == NULL) {  /* first time for this JPEG object? */
+    cinfo->src = (struct jpeg_source_mgr *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+          SIZEOF(my_source_mgr));
+    src = (my_src_ptr) cinfo->src;
+    src->buffer = (JOCTET *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+          INPUT_BUF_SIZE * SIZEOF(JOCTET));
+  }
+
+  src = (my_src_ptr) cinfo->src;
+  src->pub.init_source = reinterpret_cast<void_jpeg_decompress_struct>(init_source);
+  src->pub.fill_input_buffer = reinterpret_cast<boolean_jpeg_decompress_struct>(fill_input_buffer);
+  src->pub.skip_input_data = reinterpret_cast<void_jpeg_decompress_struct_long>(skip_input_data);
+  src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+  src->pub.term_source = reinterpret_cast<void_jpeg_decompress_struct>(term_source);
+  src->infile = infile;
+  
+  // Need to setup a new buffer, clean bytes_in_buffer and next_input_byte
+  if( flag )
+    {
+    src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+    src->pub.next_input_byte = NULL; /* until buffer loaded */
+    }
+  //only upate the new fragment, valid for both 'flag' value
+  src->frag = frag;
+  src->bytes_read = 0;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/.NoDartCoverage b/Utilities/ITK/Utilities/itkjpeg/.NoDartCoverage
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Utilities/ITK/Utilities/itkjpeg/12/CMakeLists.txt b/Utilities/ITK/Utilities/itkjpeg/12/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fdbaedeef7f441050e02ac70057b126bf7e7e18c
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/12/CMakeLists.txt
@@ -0,0 +1,9 @@
+# JPEG 12 bits project
+
+INCLUDE_DIRECTORIES(BEFORE
+  "${CMAKE_CURRENT_BINARY_DIR}"
+  "${ITKJPEG_SOURCE_DIR}")
+ADD_LIBRARY(itkjpeg12 ${JPEG_SOURCES})
+INSTALL_TARGETS(/lib/InsightToolkit itkjpeg12)
+
+
diff --git a/Utilities/ITK/Utilities/itkjpeg/16/CMakeLists.txt b/Utilities/ITK/Utilities/itkjpeg/16/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8e98dfb82c3dce165cd0cf508bb5d7398cc1abfa
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/16/CMakeLists.txt
@@ -0,0 +1,9 @@
+# JPEG 16 bits project
+
+INCLUDE_DIRECTORIES(BEFORE
+  "${CMAKE_CURRENT_BINARY_DIR}"
+  "${ITKJPEG_SOURCE_DIR}")
+ADD_LIBRARY(itkjpeg16 ${JPEG_SOURCES})
+INSTALL_TARGETS(/lib/InsightToolkit itkjpeg16)
+
+
diff --git a/Utilities/ITK/Utilities/itkjpeg/8/CMakeLists.txt b/Utilities/ITK/Utilities/itkjpeg/8/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5deb268ed0939852e1c058e39f8abc4460dd5413
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/8/CMakeLists.txt
@@ -0,0 +1,8 @@
+# JPEG 8 bits project
+
+INCLUDE_DIRECTORIES(BEFORE
+  "${CMAKE_CURRENT_BINARY_DIR}"
+  "${ITKJPEG_SOURCE_DIR}")
+ADD_LIBRARY(itkjpeg8 ${JPEG_SOURCES})
+INSTALL_TARGETS(/lib/InsightToolkit itkjpeg8)
+
diff --git a/Utilities/ITK/Utilities/itkjpeg/CMakeLists.txt b/Utilities/ITK/Utilities/itkjpeg/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..47b1bf4b57b33d3d48d55c3aa060db8262b26b00
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/CMakeLists.txt
@@ -0,0 +1,126 @@
+PROJECT(ITKJPEG)
+
+INCLUDE_REGULAR_EXPRESSION("^(jchuff|jconfig|jdct|jdhuff|jerror|jinclude|jmemsys|jmorecfg|jpegint|jpeglib|jversion|jpeg).*$")
+
+#MESSAGE(FATAL_ERROR ${ITKJPEG_SOURCE_DIR})
+#INCLUDE_DIRECTORIES(${ITKJPEG_SOURCE_DIR})
+#INCLUDE_DIRECTORIES(${ITKJPEG_BINARY_DIR})
+
+
+# memmgr back ends: compile only one of these into a working library
+# (For now, let's use the mode that requires the image fit into memory.
+# This is the recommended mode for Win32 anyway.)
+SET(systemdependent_SRCS jmemnobs.c)
+
+# library object files common to compression and decompression
+SET(common_SRCS
+jcomapi.c jutils.c jerror.c jmemmgr.c
+)
+
+# compression library object files
+SET(compression_SRCS
+jcapimin.c jcapistd.c jctrans.c jcparam.c  jcinit.c
+jcmaster.c jcmarker.c jcmainct.c jcprepct.c jccoefct.c jccolor.c
+jcsample.c jchuff.c jcphuff.c jcdctmgr.c jfdctfst.c jfdctflt.c
+jdatadst.c
+)
+
+# Lossy (DCT) codec:
+SET(comp_lossy_SRCS
+jfdctint.c
+jclossy.c
+
+# lossless
+jclossls.c
+
+jdarith.c
+jcodec.c
+jcscale.c
+jcshuff.c
+jclhuff.c
+jcpred.c
+jcdiffct.c
+)
+
+# decompression library object files
+SET(decompression_SRCS
+jdapimin.c jdapistd.c jdtrans.c  jdmaster.c
+jdinput.c jdmarker.c jdhuff.c jdphuff.c jdmainct.c jdcoefct.c
+jdpostct.c jddctmgr.c jidctfst.c jidctflt.c jidctint.c jidctred.c
+jdsample.c jdcolor.c jquant1.c jquant2.c jdmerge.c
+jdatasrc.c
+)
+
+SET(decomp_lossy_SRCS
+ jdlossls.c jdlossy.c
+jcarith.c
+jdlhuff.c
+jddiffct.c
+jdpred.c
+jdscale.c
+jdshuff.c
+)
+
+SET(JPEG_HEADER_FILES
+  jchuff.h  
+  jdct.h  
+  jdhuff.h  
+  jerror.h  
+  jinclude.h  
+  jmemsys.h  
+#  jmorecfg.h     #this one need to be configured
+  jpegint.h  
+  jpeglib.h  
+  jversion.h
+  jlossy.h
+  jlossls.h
+  )
+
+SET(JPEG_SOURCES)
+FOREACH(src
+  ${systemdependent_SRCS}
+  ${common_SRCS}
+  ${compression_SRCS}
+  ${decompression_SRCS}
+  ${comp_lossy_SRCS}
+  ${decomp_lossy_SRCS}
+  )
+  SET(JPEG_SOURCES ${JPEG_SOURCES}
+    "${ITKJPEG_SOURCE_DIR}/${src}")
+ENDFOREACH(src)
+
+IF (WIN32)
+  IF (BUILD_SHARED_LIBS)
+    ADD_DEFINITIONS(-DJPEGDLL)
+  ELSE (BUILD_SHARED_LIBS)
+    SET(JPEGSTATIC 1)
+  ENDIF (BUILD_SHARED_LIBS)
+ENDIF (WIN32)
+
+CONFIGURE_FILE(${ITKJPEG_SOURCE_DIR}/.NoDartCoverage
+               ${ITKJPEG_BINARY_DIR}/.NoDartCoverage)
+CONFIGURE_FILE(${ITKJPEG_SOURCE_DIR}/jpegDllConfig.h.in
+               ${ITKJPEG_BINARY_DIR}/jpegDllConfig.h)
+
+# Generate three libraries: jpeg 8bits, 12bits and 16bits
+# using only one source directory
+
+# Particular case jmorecfg.h needs to be specified either 8, 12 or 16 bits:
+FOREACH(bits 8 12 16)
+  SET(CMAKE_BITS_IN_JSAMPLE ${bits})
+  CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/jmorecfg.h.in
+                 ${CMAKE_CURRENT_BINARY_DIR}/${bits}/jmorecfg.h @ONLY IMMEDIATE)
+  SET(BITS_TYPE_JPEG_MANGLE_NAME "itkjpeg/mangle_jpeg${bits}bits.h")
+  CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/jconfig.h.in
+                 ${CMAKE_CURRENT_BINARY_DIR}/${bits}/jconfig.h @ONLY IMMEDIATE)
+  # Dummy copy for ITK to include <jpeg/8/jpeglib.h> with no conflict
+  CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/jpeglib.h
+                 ${CMAKE_CURRENT_BINARY_DIR}/${bits}/jpeglib.h COPYONLY IMMEDIATE)
+  CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/jerror.h
+                 ${CMAKE_CURRENT_BINARY_DIR}/${bits}/jerror.h COPYONLY IMMEDIATE)
+  CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/jinclude.h
+                 ${CMAKE_CURRENT_BINARY_DIR}/${bits}/jinclude.h COPYONLY IMMEDIATE)
+ENDFOREACH(bits)
+
+SUBDIRS(8 12 16)
+
diff --git a/Utilities/ITK/Utilities/itkjpeg/COPYRIGHT.dcmtk b/Utilities/ITK/Utilities/itkjpeg/COPYRIGHT.dcmtk
new file mode 100644
index 0000000000000000000000000000000000000000..4c0359f241711aac462ffcf10aa651f9b72bddfa
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/COPYRIGHT.dcmtk
@@ -0,0 +1,258 @@
+
+COPYRIGHT
+
+Unless otherwise specified, the DCMTK software package has the
+following copyright:
+
+/*
+ *  Copyright (C) 1994-2004, OFFIS
+ *
+ *  This software and supporting documentation were developed by
+ *
+ *    Kuratorium OFFIS e.V.
+ *    Healthcare Information and Communication Systems
+ *    Escherweg 2
+ *    D-26121 Oldenburg, Germany
+ *
+ *  THIS SOFTWARE IS MADE AVAILABLE,  AS IS,  AND OFFIS MAKES NO  WARRANTY
+ *  REGARDING  THE  SOFTWARE,  ITS  PERFORMANCE,  ITS  MERCHANTABILITY  OR
+ *  FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES  OR
+ *  ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
+ *  PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
+ *
+ *  Copyright of the software  and  supporting  documentation  is,  unless
+ *  otherwise stated, owned by OFFIS, and free access is hereby granted as
+ *  a license to  use  this  software,  copy  this  software  and  prepare
+ *  derivative works based upon this software.  However, any  distribution
+ *  of this software source code or supporting documentation or derivative
+ *  works  (source code and  supporting documentation)  must  include  the
+ *  three paragraphs of this copyright notice.
+ *
+ */
+
+Some portions of the DCMTK software package are derived from earlier
+versions of this software with the following copyright, and can be
+identifed by the following copyright notice located in each source file:
+
+/*
+ *  Copyright (C) 1993/1994, OFFIS, Oldenburg University and CERIUM
+ *
+ *  This software and supporting documentation were
+ *  developed by
+ *
+ *    Institut OFFIS
+ *    Bereich Kommunikationssysteme
+ *    Westerstr. 10-12
+ *    26121 Oldenburg, Germany
+ *
+ *    Fachbereich Informatik
+ *    Abteilung Prozessinformatik
+ *    Carl von Ossietzky Universitaet Oldenburg
+ *    Ammerlaender Heerstr. 114-118
+ *    26111 Oldenburg, Germany
+ *
+ *    CERIUM
+ *    Laboratoire SIM
+ *    Faculte de Medecine
+ *    2 Avenue du Pr. Leon Bernard
+ *    35043 Rennes Cedex, France
+ *
+ *  for CEN/TC251/WG4 as a contribution to the Radiological
+ *  Society of North America (RSNA) 1993 Digital Imaging and
+ *  Communications in Medicine (DICOM) Demonstration.
+ *
+ *  THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND NEITHER OFFIS,
+ *  OLDENBURG UNIVERSITY NOR CERIUM MAKE ANY WARRANTY REGARDING
+ *  THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR
+ *  FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER
+ *  DISEASES OR ITS CONFORMITY TO ANY SPECIFICATION.  THE
+ *  ENTIRE RISK AS TO QUALITY AND PERFORMANCE OF THE SOFTWARE
+ *  IS WITH THE USER.
+ *
+ *  Copyright of the software and supporting documentation
+ *  is, unless otherwise stated, jointly owned by OFFIS,
+ *  Oldenburg University and CERIUM and free access is hereby
+ *  granted as a license to use this software, copy this
+ *  software and prepare derivative works based upon this
+ *  software. However, any distribution of this software
+ *  source code or supporting documentation or derivative
+ *  works (source code and supporting documentation) must
+ *  include the three paragraphs of this copyright notice.
+ *
+ */
+
+Some other parts of this software within the dcmtk/dcmnet
+sub-package related to the DICOM Upper Layer Protocol are
+derived from software developed for the RSNA'93 DICOM
+demonstration and kindly made available to us by the Mallinckrodt
+Institute of Radiology.  Such software can be identifed by the
+following copyright notice located in each affected source file:
+
+/*
+ *  Copyright (C) 1993, RSNA and Washington University
+ *
+ *  The software and supporting documentation for the Radiological
+ *  Society of North America (RSNA) 1993 Digital Imaging and
+ *  Communications in Medicine (DICOM) Demonstration were developed
+ *  at the
+ *          Electronic Radiology Laboratory
+ *          Mallinckrodt Institute of Radiology
+ *          Washington University School of Medicine
+ *          510 S. Kingshighway Blvd.
+ *          St. Louis, MO 63110
+ *  as part of the 1993 DICOM Central Test Node project for, and
+ *  under contract with, the Radiological Society of North America.
+ *
+ *  THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND NEITHER RSNA NOR
+ *  WASHINGTON UNIVERSITY MAKE ANY WARRANTY ABOUT THE SOFTWARE, ITS
+ *  PERFORMANCE, ITS MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR
+ *  USE, FREEDOM FROM ANY COMPUTER DISEASES OR ITS CONFORMITY TO ANY
+ *  SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND PERFORMANCE OF
+ *  THE SOFTWARE IS WITH THE USER.
+ *
+ *  Copyright of the software and supporting documentation is
+ *  jointly owned by RSNA and Washington University, and free access
+ *  is hereby granted as a license to use this software, copy this
+ *  software and prepare derivative works based upon this software.
+ *  However, any distribution of this software source code or
+ *  supporting documentation or derivative works (source code and
+ *  supporting documentation) must include the three paragraphs of
+ *  the copyright notice.
+ */
+
+The dcmjpeg sub-package includes an adapted version of the Independent JPEG
+Group Toolkit Version 6b, which is contained in dcmjpeg/libijg8,
+dcmjpeg/libijg12 and dcmjpeg/libijg16.  This toolkit is covered by the
+following copyright.  The original README file for the Independent JPEG
+Group Toolkit is located in dcmjpeg/docs/ijg_readme.txt.
+
+/*
+ *  The authors make NO WARRANTY or representation, either express or implied,
+ *  with respect to this software, its quality, accuracy, merchantability, or
+ *  fitness for a particular purpose.  This software is provided "AS IS", and you,
+ *  its user, assume the entire risk as to its quality and accuracy.
+ *
+ *  This software is copyright (C) 1991-1998, Thomas G. Lane.
+ *  All Rights Reserved except as specified below.
+ *
+ *  Permission is hereby granted to use, copy, modify, and distribute this
+ *  software (or portions thereof) for any purpose, without fee, subject to these
+ *  conditions:
+ *  (1) If any part of the source code for this software is distributed, then this
+ *  README file must be included, with this copyright and no-warranty notice
+ *  unaltered; and any additions, deletions, or changes to the original files
+ *  must be clearly indicated in accompanying documentation.
+ *  (2) If only executable code is distributed, then the accompanying
+ *  documentation must state that "this software is based in part on the work of
+ *  the Independent JPEG Group".
+ *  (3) Permission for use of this software is granted only if the user accepts
+ *  full responsibility for any undesirable consequences; the authors accept
+ *  NO LIABILITY for damages of any kind.
+ *
+ *  These conditions apply to any software derived from or based on the IJG code,
+ *  not just to the unmodified library.  If you use our work, you ought to
+ *  acknowledge us.
+ *
+ *  Permission is NOT granted for the use of any IJG author's name or company name
+ *  in advertising or publicity relating to this software or products derived from
+ *  it.  This software may be referred to only as "the Independent JPEG Group's
+ *  software".
+ *
+ *  We specifically permit and encourage the use of this software as the basis of
+ *  commercial products, provided that all warranty or liability claims are
+ *  assumed by the product vendor.
+ */
+
+
+The color quantization code in module dcmimage (dcmquant and the related
+classes) is derived from code written by Jef Poskanzer for the NetPBM
+toolkit which has the following copyright:
+
+/*
+ * Copyright (C) 1989, 1991 by Jef Poskanzer.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  This software is provided "as is" without express or
+ * implied warranty.
+ */
+
+
+The code for the OFStandard::strlcpy and OFStandard::strlcat helper
+functions in ofstd/libsrc/ofstd.cc has been derived from the BSD
+implementation of strlcpy() and strlcat() and which carries the
+following copyright notice:
+
+/*
+ *  Copyright (c) 1998 Todd C. Miller <Todd.Miller(at)courtesan.com>
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ *  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+The code for the OFStandard::atof helper function in
+ofstd/libsrc/ofstd.cc has been derived from an implementation which
+carries the following copyright notice:
+
+/*
+ *  Copyright 1988 Regents of the University of California
+ *  Permission to use, copy, modify, and distribute this software and
+ *  its documentation for any purpose and without fee is hereby granted,
+ *  provided that the above copyright notice appear in all copies.  The
+ *  University of California makes no representations about the
+ *  suitability of this software for any purpose.  It is provided "as
+ *  is" without express or implied warranty.
+ *
+ *
+ *  The code for OFStandard::ftoa has been derived
+ *  from an implementation which carries the following copyright notice:
+ *
+ *  Copyright (c) 1988 Regents of the University of California.
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms are permitted
+ *  provided that the above copyright notice and this paragraph are
+ *  duplicated in all such forms and that any documentation,
+ *  advertising materials, and other materials related to such
+ *  distribution and use acknowledge that the software was developed
+ *  by the University of California, Berkeley.  The name of the
+ *  University may not be used to endorse or promote products derived
+ *  from this software without specific prior written permission.
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ *  WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+The "Base64" encoder/decoder in ofstd/libsrc/ofstd.cc has been derived
+from an implementation which carries the following copyright notice:
+
+/*
+ *  Copyright (c) 1999, Bob Withers - bwit(at)pobox.com
+ *
+ *  This code may be freely used for any purpose, either personal or commercial,
+ *  provided the authors copyright notice remains intact.
+ */
+
diff --git a/Utilities/ITK/Utilities/itkjpeg/README b/Utilities/ITK/Utilities/itkjpeg/README
new file mode 100644
index 0000000000000000000000000000000000000000..242359479d6c40f7da40f80f0ebc08adfe0b6b29
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/README
@@ -0,0 +1,385 @@
+The Independent JPEG Group's JPEG software
+==========================================
+
+README for release 6b of 27-Mar-1998
+====================================
+
+This distribution contains the sixth public release of the Independent JPEG
+Group's free JPEG software.  You are welcome to redistribute this software and
+to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
+
+Serious users of this software (particularly those incorporating it into
+larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to
+our electronic mailing list.  Mailing list members are notified of updates
+and have a chance to participate in technical discussions, etc.
+
+This software is the work of Tom Lane, Philip Gladstone, Jim Boucher,
+Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi,
+Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG
+Group.
+
+IJG is not affiliated with the official ISO JPEG standards committee.
+
+
+DOCUMENTATION ROADMAP
+=====================
+
+This file contains the following sections:
+
+OVERVIEW            General description of JPEG and the IJG software.
+LEGAL ISSUES        Copyright, lack of warranty, terms of distribution.
+REFERENCES          Where to learn more about JPEG.
+ARCHIVE LOCATIONS   Where to find newer versions of this software.
+RELATED SOFTWARE    Other stuff you should get.
+FILE FORMAT WARS    Software *not* to get.
+TO DO               Plans for future IJG releases.
+
+Other documentation files in the distribution are:
+
+User documentation:
+  install.doc       How to configure and install the IJG software.
+  usage.doc         Usage instructions for cjpeg, djpeg, jpegtran,
+                    rdjpgcom, and wrjpgcom.
+  *.1               Unix-style man pages for programs (same info as usage.doc).
+  wizard.doc        Advanced usage instructions for JPEG wizards only.
+  change.log        Version-to-version change highlights.
+Programmer and internal documentation:
+  libjpeg.doc       How to use the JPEG library in your own programs.
+  example.c         Sample code for calling the JPEG library.
+  structure.doc     Overview of the JPEG library's internal structure.
+  filelist.doc      Road map of IJG files.
+  coderules.doc     Coding style rules --- please read if you contribute code.
+
+Please read at least the files install.doc and usage.doc.  Useful information
+can also be found in the JPEG FAQ (Frequently Asked Questions) article.  See
+ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
+
+If you want to understand how the JPEG code works, we suggest reading one or
+more of the REFERENCES, then looking at the documentation files (in roughly
+the order listed) before diving into the code.
+
+
+OVERVIEW
+========
+
+This package contains C software to implement JPEG image compression and
+decompression.  JPEG (pronounced "jay-peg") is a standardized compression
+method for full-color and gray-scale images.  JPEG is intended for compressing
+"real-world" scenes; line drawings, cartoons and other non-realistic images
+are not its strong suit.  JPEG is lossy, meaning that the output image is not
+exactly identical to the input image.  Hence you must not use JPEG if you
+have to have identical output bits.  However, on typical photographic images,
+very good compression levels can be obtained with no visible change, and
+remarkably high compression levels are possible if you can tolerate a
+low-quality image.  For more details, see the references, or just experiment
+with various compression settings.
+
+This software implements JPEG baseline, extended-sequential, progressive
+and lossless compression processes.  Provision is made for supporting all
+variants of these processes, although some uncommon parameter settings aren't
+implemented yet. For legal reasons, we are not distributing code for the
+arithmetic-coding variants of JPEG; see LEGAL ISSUES.  We have made no
+provision for supporting the hierarchical processes defined in the standard.
+
+We provide a set of library routines for reading and writing JPEG image files,
+plus two sample applications "cjpeg" and "djpeg", which use the library to
+perform conversion between JPEG and some other popular image file formats.
+The library is intended to be reused in other applications.
+
+In order to support file conversion and viewing software, we have included
+considerable functionality beyond the bare JPEG coding/decoding capability;
+for example, the color quantization modules are not strictly part of JPEG
+decoding, but they are essential for output to colormapped file formats or
+colormapped displays.  These extra functions can be compiled out of the
+library if not required for a particular application.  We have also included
+"jpegtran", a utility for lossless transcoding between different JPEG
+processes, and "rdjpgcom" and "wrjpgcom", two simple applications for
+inserting and extracting textual comments in JFIF files.
+
+The emphasis in designing this software has been on achieving portability and
+flexibility, while also making it fast enough to be useful.  In particular,
+the software is not intended to be read as a tutorial on JPEG.  (See the
+REFERENCES section for introductory material.)  Rather, it is intended to
+be reliable, portable, industrial-strength code.  We do not claim to have
+achieved that goal in every aspect of the software, but we strive for it.
+
+We welcome the use of this software as a component of commercial products.
+No royalty is required, but we do ask for an acknowledgement in product
+documentation, as described under LEGAL ISSUES.
+
+
+LEGAL ISSUES
+============
+
+In plain English:
+
+1. We don't promise that this software works.  (But if you find any bugs,
+   please let us know!)
+2. You can use this software for whatever you want.  You don't have to pay us.
+3. You may not pretend that you wrote this software.  If you use it in a
+   program, you must acknowledge somewhere in your documentation that
+   you've used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose.  This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-1998, Thomas G. Lane.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library.  If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it.  This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+by the usual distribution terms of the Free Software Foundation; principally,
+that you must include source code if you redistribute it.  (See the file
+ansi2knr.c for full details.)  However, since ansi2knr.c is not needed as part
+of any program generated from the IJG code, this does not limit you more than
+the foregoing paragraphs do.
+
+The Unix configuration script "configure" was produced with GNU Autoconf.
+It is copyright by the Free Software Foundation but is freely distributable.
+The same holds for its supporting scripts (config.guess, config.sub,
+ltconfig, ltmain.sh).  Another support script, install-sh, is copyright
+by M.I.T. but is also freely distributable.
+
+It appears that the arithmetic coding option of the JPEG spec is covered by
+patents owned by IBM, AT&T, and Mitsubishi.  Hence arithmetic coding cannot
+legally be used without obtaining one or more licenses.  For this reason,
+support for arithmetic coding has been removed from the free JPEG software.
+(Since arithmetic coding provides only a marginal gain over the unpatented
+Huffman mode, it is unlikely that very many implementations will support it.)
+So far as we are aware, there are no patent restrictions on the remaining
+code.
+
+The IJG distribution formerly included code to read and write GIF files.
+To avoid entanglement with the Unisys LZW patent, GIF reading support has
+been removed altogether, and the GIF writer has been simplified to produce
+"uncompressed GIFs".  This technique does not use the LZW algorithm; the
+resulting GIF files are larger than usual, but are readable by all standard
+GIF decoders.
+
+We are required to state that
+    "The Graphics Interchange Format(c) is the Copyright property of
+    CompuServe Incorporated.  GIF(sm) is a Service Mark property of
+    CompuServe Incorporated."
+
+
+REFERENCES
+==========
+
+We highly recommend reading one or more of these references before trying to
+understand the innards of the JPEG software.
+
+The best short technical introduction to the JPEG compression algorithm is
+	Wallace, Gregory K.  "The JPEG Still Picture Compression Standard",
+	Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
+(Adjacent articles in that issue discuss MPEG motion picture compression,
+applications of JPEG, and related topics.)  If you don't have the CACM issue
+handy, a PostScript file containing a revised version of Wallace's article is
+available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz.  The file (actually
+a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
+omits the sample images that appeared in CACM, but it includes corrections
+and some added material.  Note: the Wallace article is copyright ACM and IEEE,
+and it may not be used for commercial purposes.
+
+A somewhat less technical, more leisurely introduction to JPEG can be found in
+"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
+M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1.  This book provides
+good explanations and example C code for a multitude of compression methods
+including JPEG.  It is an excellent source if you are comfortable reading C
+code but don't know much about data compression in general.  The book's JPEG
+sample code is far from industrial-strength, but when you are ready to look
+at a full implementation, you've got one here...
+
+The best full description of JPEG is the textbook "JPEG Still Image Data
+Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published
+by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1.  Price US$59.95, 638 pp.
+The book includes the complete text of the ISO JPEG standards (DIS 10918-1
+and draft DIS 10918-2).  This is by far the most complete exposition of JPEG
+in existence, and we highly recommend it.
+
+The JPEG standard itself is not available electronically; you must order a
+paper copy through ISO or ITU.  (Unless you feel a need to own a certified
+official copy, we recommend buying the Pennebaker and Mitchell book instead;
+it's much cheaper and includes a great deal of useful explanatory material.)
+In the USA, copies of the standard may be ordered from ANSI Sales at (212)
+642-4900, or from Global Engineering Documents at (800) 854-7179.  (ANSI
+doesn't take credit card orders, but Global does.)  It's not cheap: as of
+1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7%
+shipping/handling.  The standard is divided into two parts, Part 1 being the
+actual specification, while Part 2 covers compliance testing methods.  Part 1
+is titled "Digital Compression and Coding of Continuous-tone Still Images,
+Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
+10918-1, ITU-T T.81.  Part 2 is titled "Digital Compression and Coding of
+Continuous-tone Still Images, Part 2: Compliance testing" and has document
+numbers ISO/IEC IS 10918-2, ITU-T T.83.
+
+Some extensions to the original JPEG standard are defined in JPEG Part 3,
+a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84.  IJG
+currently does not support any Part 3 extensions.
+
+The JPEG standard does not specify all details of an interchangeable file
+format.  For the omitted details we follow the "JFIF" conventions, revision
+1.02.  A copy of the JFIF spec is available from:
+	Literature Department
+	C-Cube Microsystems, Inc.
+	1778 McCarthy Blvd.
+	Milpitas, CA 95035
+	phone (408) 944-6300,  fax (408) 944-6314
+A PostScript version of this document is available by FTP at
+ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz.  There is also a plain text
+version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing
+the figures.
+
+The TIFF 6.0 file format specification can be obtained by FTP from
+ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz.  The JPEG incorporation scheme
+found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
+IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
+Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
+(Compression tag 7).  Copies of this Note can be obtained from ftp.sgi.com or
+from ftp://ftp.uu.net/graphics/jpeg/.  It is expected that the next revision
+of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
+Although IJG's own code does not support TIFF/JPEG, the free libtiff library
+uses our library to implement TIFF/JPEG per the Note.  libtiff is available
+from ftp://ftp.sgi.com/graphics/tiff/.
+
+
+ARCHIVE LOCATIONS
+=================
+
+The "official" archive site for this software is ftp.uu.net (Internet
+address 192.48.96.9).  The most recent released version can always be found
+there in directory graphics/jpeg.  This particular version will be archived
+as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz.  If you don't have
+direct Internet access, UUNET's archives are also available via UUCP; contact
+help@uunet.uu.net for information on retrieving files that way.
+
+Numerous Internet sites maintain copies of the UUNET files.  However, only
+ftp.uu.net is guaranteed to have the latest official version.
+
+You can also obtain this software in DOS-compatible "zip" archive format from
+the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or
+on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12
+"JPEG Tools".  Again, these versions may sometimes lag behind the ftp.uu.net
+release.
+
+The JPEG FAQ (Frequently Asked Questions) article is a useful source of
+general information about JPEG.  It is updated constantly and therefore is
+not included in this distribution.  The FAQ is posted every two weeks to
+Usenet newsgroups comp.graphics.misc, news.answers, and other groups.
+It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
+and other news.answers archive sites, including the official news.answers
+archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
+If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
+with body
+	send usenet/news.answers/jpeg-faq/part1
+	send usenet/news.answers/jpeg-faq/part2
+
+
+RELATED SOFTWARE
+================
+
+Numerous viewing and image manipulation programs now support JPEG.  (Quite a
+few of them use this library to do so.)  The JPEG FAQ described above lists
+some of the more popular free and shareware viewers, and tells where to
+obtain them on Internet.
+
+If you are on a Unix machine, we highly recommend Jef Poskanzer's free
+PBMPLUS software, which provides many useful operations on PPM-format image
+files.  In particular, it can convert PPM images to and from a wide range of
+other formats, thus making cjpeg/djpeg considerably more useful.  The latest
+version is distributed by the NetPBM group, and is available from numerous
+sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/.
+Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is;
+you are likely to have difficulty making it work on any non-Unix machine.
+
+A different free JPEG implementation, written by the PVRG group at Stanford,
+is available from ftp://havefun.stanford.edu/pub/jpeg/.  This program
+is designed for research and experimentation rather than production use;
+it is slower, harder to use, and less portable than the IJG code, but it
+is easier to read and modify.  Also, the PVRG code supports lossless JPEG,
+which we do not.  (On the other hand, it doesn't do progressive JPEG.)
+
+
+FILE FORMAT WARS
+================
+
+Some JPEG programs produce files that are not compatible with our library.
+The root of the problem is that the ISO JPEG committee failed to specify a
+concrete file format.  Some vendors "filled in the blanks" on their own,
+creating proprietary formats that no one else could read.  (For example, none
+of the early commercial JPEG implementations for the Macintosh were able to
+exchange compressed files.)
+
+The file format we have adopted is called JFIF (see REFERENCES).  This format
+has been agreed to by a number of major commercial JPEG vendors, and it has
+become the de facto standard.  JFIF is a minimal or "low end" representation.
+We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF
+Technical Note #2) for "high end" applications that need to record a lot of
+additional data about an image.  TIFF/JPEG is fairly new and not yet widely
+supported, unfortunately.
+
+The upcoming JPEG Part 3 standard defines a file format called SPIFF.
+SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should
+be able to read the most common variant of SPIFF.  SPIFF has some technical
+advantages over JFIF, but its major claim to fame is simply that it is an
+official standard rather than an informal one.  At this point it is unclear
+whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto
+standard.  IJG intends to support SPIFF once the standard is frozen, but we
+have not decided whether it should become our default output format or not.
+(In any case, our decoder will remain capable of reading JFIF indefinitely.)
+
+Various proprietary file formats incorporating JPEG compression also exist.
+We have little or no sympathy for the existence of these formats.  Indeed,
+one of the original reasons for developing this free software was to help
+force convergence on common, open format standards for JPEG files.  Don't
+use a proprietary file format!
+
+
+TO DO
+=====
+
+The major thrust for v7 will probably be improvement of visual quality.
+The current method for scaling the quantization tables is known not to be
+very good at low Q values.  We also intend to investigate block boundary
+smoothing, "poor man's variable quantization", and other means of improving
+quality-vs-file-size performance without sacrificing compatibility.
+
+In future versions, we are considering supporting some of the upcoming JPEG
+Part 3 extensions --- principally, variable quantization and the SPIFF file
+format.
+
+As always, speeding things up is of great interest.
+
+Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net.
diff --git a/Utilities/ITK/Utilities/itkjpeg/README.GDCM.txt b/Utilities/ITK/Utilities/itkjpeg/README.GDCM.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e88393ae9d5bed3e3ea3ba21d63f42914ea4a865
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/README.GDCM.txt
@@ -0,0 +1,105 @@
+This directory contains a subset of the Independent JPEG Group's (IJG)
+libjpeg version 6b.  We only include enough of distribution to build
+libjpeg.  We do not include the standard executables that come with
+libjpeg (cjpeg, djpeg, etc.). Furthermore, the standard libjpeg build
+process is replaced with a CMake build process.
+
+We'd like to thank the IJG for distributing a public JPEG IO library.
+
+We'd like to also thank the dcmtk crew for releasing their toolkit under such a nice license that allow us to patch ijg properly to handle all sort of jpeg compression found in the DICOM implementation. The copyright can be found in COPYRIGHT.dcmtk.
+
+Modifications
+-------------
+
+1.
+jconfig.h is usually generated by the build process. For this distribution,
+we ship a version of jconfig.h.in to be used across several platforms. It's 
+purpose is also to allow generation of both 8bits and 12bits lib.
+
+
+
+2.
+jdhuff.c was modified to support special Philips MRI image:
+
+Index: jdhuff.c
+===================================================================
+RCS file: /cvs/public/gdcm/src/jpeg/libijg8/jdhuff.c,v
+retrieving revision 1.1
+diff -u -3 -p -r1.1 jdhuff.c
+--- jdhuff.c    24 Jun 2003 10:09:48 -0000      1.1
++++ jdhuff.c    7 Oct 2004 02:29:43 -0000
+@@ -259,8 +259,11 @@ jpeg_make_d_derived_tbl (j_decompress_pt
+   if (isDC) {
+     for (i = 0; i < numsymbols; i++) {
+       int sym = htbl->huffval[i];
+-      if (sym < 0 || sym > 15)
+-       ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
++      if (sym < 0 || sym > 15) {
++         // Now, we can read Philips MRI Images
++         htbl->huffval[i]=15;
++//     ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
++      }
+     }
+   }
+ }
+
+
+3.
+jmorecfg.h was modified so that we can modify it automatically at build time to
+either generate a 8bits jpeg lib or 12bits jpeg library:
+
+Index: jmorecfg.h
+===================================================================
+RCS file: /cvs/public/gdcm/src/jpeg/libijg8/jmorecfg.h,v
+retrieving revision 1.4
+diff -u -3 -p -r1.4 jmorecfg.h
+--- jmorecfg.h  31 Oct 2003 14:59:50 -0000      1.4
++++ jmorecfg.h  7 Oct 2004 02:30:40 -0000
+@@ -19,7 +19,8 @@
+  * We do not support run-time selection of data precision, sorry.
+  */
+
+-#define BITS_IN_JSAMPLE  8     /* use 8 or 12 */
++//#define BITS_IN_JSAMPLE  8   /* use 8 or 12 */
++#define BITS_IN_JSAMPLE @GDCM_BITS_IN_JSAMPLE@
+
+ /*
+  * Maximum number of components (color channels) allowed in JPEG image.
+
+
+
+
+4.
+To further allow us to have to different copy of the 8, 12 and 16 bits jpeg
+library we had to mangle the name. Fur this purpose two new file were added to
+the library: gdcm_mangle_8bits.h, gdcm_mangle_12bits.h and gdcm_mangle_16bits.h. 
+Those file were generated using:
+
+        nm libgdcmijpeg8.a | grep " [R|T] " | colrm 1 11 | sort
+
+
+5.
+In order to read lossless images, we had to apply the ls-patch to jpeg-6b. So I started from scratch:
+
+tar xvfz /tmp/jpegsrc.v6b.tar.gz                        (1)
+patch < /tmp/ljpeg-6b.patch                             (2)
+patch -p0 < arithmetic-without-arith-option-full.patch  (3)
+patch -p0 < warnings10-14.patch                         (4)
+patch -p0 < previous-gdcm.patch                         (5)
+-----------------------------------------------------------
+= The subdir src/jpeg/libijg
+
+(now I also need to apply the redhat patch for cplusplus lib) 
+
+(1) http://www.ijg.org/files/jpegsrc.v6b.tar.gz
+(2) http://www.oceana.com/ftp/ljpeg/ljpeg-patch.v6b.tar.gz
+(3), (4) and (5) http://www.creatis.insa-lyon.fr/~malaterre/jpeg/
+
+(3) Was made with a carefull inspection of dcmtk code (see convert.sh at the same spot as the patch)
+(4) Is basically just compilation of the lib with -W -Wall -Werror
+(5) This contains some configuration copy/paste from VTK, and the 'well known' 12 bits Philips MRI DICOM patch
+
+
+
+NOTE for later:
+(shoud we disable getenv just as dcmtk ? there is a ijg flag for that NO_ENV or something similar
diff --git a/Utilities/ITK/Utilities/itkjpeg/README.ITK.txt b/Utilities/ITK/Utilities/itkjpeg/README.ITK.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ebe67e264bdfca69aefb09f05facb6902ed7b5f0
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/README.ITK.txt
@@ -0,0 +1,22 @@
+This directory contains a subset of the Independent JPEG Group's (IJG)
+libjpeg version 6b.  We only include enough of distribution to build
+libjpeg.  We do not include the standard executables that come with
+libjpeg (cjpeg, djpeg, etc.). Furthermore, the standard libjpeg build
+process is replaced with a CMake build process.
+
+We'd like to thank the IJG for distributing a public JPEG IO library.
+
+Modifications
+-------------
+
+jconfig.h is usually generated by the build process. For this distribution, 
+we ship a version of jconfig.h to be used across several platforms.
+
+jmorecfg.h was altered to support Windows DLL generation. We also
+changed the typedef INT32 to be an "int" instead of a "long". 
+
+
+
+
+
+
diff --git a/Utilities/ITK/Utilities/itkjpeg/change.log b/Utilities/ITK/Utilities/itkjpeg/change.log
new file mode 100644
index 0000000000000000000000000000000000000000..74102c0db5aa2bf3dae6f3f54673b1a257004aee
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/change.log
@@ -0,0 +1,217 @@
+CHANGE LOG for Independent JPEG Group's JPEG software
+
+
+Version 6b  27-Mar-1998
+-----------------------
+
+jpegtran has new features for lossless image transformations (rotation
+and flipping) as well as "lossless" reduction to grayscale.
+
+jpegtran now copies comments by default; it has a -copy switch to enable
+copying all APPn blocks as well, or to suppress comments.  (Formerly it
+always suppressed comments and APPn blocks.)  jpegtran now also preserves
+JFIF version and resolution information.
+
+New decompressor library feature: COM and APPn markers found in the input
+file can be saved in memory for later use by the application.  (Before,
+you had to code this up yourself with a custom marker processor.)
+
+There is an unused field "void * client_data" now in compress and decompress
+parameter structs; this may be useful in some applications.
+
+JFIF version number information is now saved by the decoder and accepted by
+the encoder.  jpegtran uses this to copy the source file's version number,
+to ensure "jpegtran -copy all" won't create bogus files that contain JFXX
+extensions but claim to be version 1.01.  Applications that generate their
+own JFXX extension markers also (finally) have a supported way to cause the
+encoder to emit JFIF version number 1.02.
+
+djpeg's trace mode reports JFIF 1.02 thumbnail images as such, rather
+than as unknown APP0 markers.
+
+In -verbose mode, djpeg and rdjpgcom will try to print the contents of
+APP12 markers as text.  Some digital cameras store useful text information
+in APP12 markers.
+
+Handling of truncated data streams is more robust: blocks beyond the one in
+which the error occurs will be output as uniform gray, or left unchanged
+if decoding a progressive JPEG.  The appearance no longer depends on the
+Huffman tables being used.
+
+Huffman tables are checked for validity much more carefully than before.
+
+To avoid the Unisys LZW patent, djpeg's GIF output capability has been
+changed to produce "uncompressed GIFs", and cjpeg's GIF input capability
+has been removed altogether.  We're not happy about it either, but there
+seems to be no good alternative.
+
+The configure script now supports building libjpeg as a shared library
+on many flavors of Unix (all the ones that GNU libtool knows how to
+build shared libraries for).  Use "./configure --enable-shared" to
+try this out.
+
+New jconfig file and makefiles for Microsoft Visual C++ and Developer Studio.
+Also, a jconfig file and a build script for Metrowerks CodeWarrior
+on Apple Macintosh.  makefile.dj has been updated for DJGPP v2, and there
+are miscellaneous other minor improvements in the makefiles.
+
+jmemmac.c now knows how to create temporary files following Mac System 7
+conventions.
+
+djpeg's -map switch is now able to read raw-format PPM files reliably.
+
+cjpeg -progressive -restart no longer generates any unnecessary DRI markers.
+
+Multiple calls to jpeg_simple_progression for a single JPEG object
+no longer leak memory.
+
+
+Version 6a  7-Feb-96
+--------------------
+
+Library initialization sequence modified to detect version mismatches
+and struct field packing mismatches between library and calling application.
+This change requires applications to be recompiled, but does not require
+any application source code change.
+
+All routine declarations changed to the style "GLOBAL(type) name ...",
+that is, GLOBAL, LOCAL, METHODDEF, EXTERN are now macros taking the
+routine's return type as an argument.  This makes it possible to add
+Microsoft-style linkage keywords to all the routines by changing just
+these macros.  Note that any application code that was using these macros
+will have to be changed.
+
+DCT coefficient quantization tables are now stored in normal array order
+rather than zigzag order.  Application code that calls jpeg_add_quant_table,
+or otherwise manipulates quantization tables directly, will need to be
+changed.  If you need to make such code work with either older or newer
+versions of the library, a test like "#if JPEG_LIB_VERSION >= 61" is
+recommended.
+
+djpeg's trace capability now dumps DQT tables in natural order, not zigzag
+order.  This allows the trace output to be made into a "-qtables" file
+more easily.
+
+New system-dependent memory manager module for use on Apple Macintosh.
+
+Fix bug in cjpeg's -smooth option: last one or two scanlines would be
+duplicates of the prior line unless the image height mod 16 was 1 or 2.
+
+Repair minor problems in VMS, BCC, MC6 makefiles.
+
+New configure script based on latest GNU Autoconf.
+
+Correct the list of include files needed by MetroWerks C for ccommand().
+
+Numerous small documentation updates.
+
+
+Version 6  2-Aug-95
+-------------------
+
+Progressive JPEG support: library can read and write full progressive JPEG
+files.  A "buffered image" mode supports incremental decoding for on-the-fly
+display of progressive images.  Simply recompiling an existing IJG-v5-based
+decoder with v6 should allow it to read progressive files, though of course
+without any special progressive display.
+
+New "jpegtran" application performs lossless transcoding between different
+JPEG formats; primarily, it can be used to convert baseline to progressive
+JPEG and vice versa.  In support of jpegtran, the library now allows lossless
+reading and writing of JPEG files as DCT coefficient arrays.  This ability
+may be of use in other applications.
+
+Notes for programmers:
+* We changed jpeg_start_decompress() to be able to suspend; this makes all
+decoding modes available to suspending-input applications.  However,
+existing applications that use suspending input will need to be changed
+to check the return value from jpeg_start_decompress().  You don't need to
+do anything if you don't use a suspending data source.
+* We changed the interface to the virtual array routines: access_virt_array
+routines now take a count of the number of rows to access this time.  The
+last parameter to request_virt_array routines is now interpreted as the
+maximum number of rows that may be accessed at once, but not necessarily
+the height of every access.
+
+
+Version 5b  15-Mar-95
+---------------------
+
+Correct bugs with grayscale images having v_samp_factor > 1.
+
+jpeg_write_raw_data() now supports output suspension.
+
+Correct bugs in "configure" script for case of compiling in
+a directory other than the one containing the source files.
+
+Repair bug in jquant1.c: sometimes didn't use as many colors as it could.
+
+Borland C makefile and jconfig file work under either MS-DOS or OS/2.
+
+Miscellaneous improvements to documentation.
+
+
+Version 5a  7-Dec-94
+--------------------
+
+Changed color conversion roundoff behavior so that grayscale values are
+represented exactly.  (This causes test image files to change.)
+
+Make ordered dither use 16x16 instead of 4x4 pattern for a small quality
+improvement.
+
+New configure script based on latest GNU Autoconf.
+Fix configure script to handle CFLAGS correctly.
+Rename *.auto files to *.cfg, so that configure script still works if
+file names have been truncated for DOS.
+
+Fix bug in rdbmp.c: didn't allow for extra data between header and image.
+
+Modify rdppm.c/wrppm.c to handle 2-byte raw PPM/PGM formats for 12-bit data.
+
+Fix several bugs in rdrle.c.
+
+NEED_SHORT_EXTERNAL_NAMES option was broken.
+
+Revise jerror.h/jerror.c for more flexibility in message table.
+
+Repair oversight in jmemname.c NO_MKTEMP case: file could be there
+but unreadable.
+
+
+Version 5  24-Sep-94
+--------------------
+
+Version 5 represents a nearly complete redesign and rewrite of the IJG
+software.  Major user-visible changes include:
+  * Automatic configuration simplifies installation for most Unix systems.
+  * A range of speed vs. image quality tradeoffs are supported.
+    This includes resizing of an image during decompression: scaling down
+    by a factor of 1/2, 1/4, or 1/8 is handled very efficiently.
+  * New programs rdjpgcom and wrjpgcom allow insertion and extraction
+    of text comments in a JPEG file.
+
+The application programmer's interface to the library has changed completely.
+Notable improvements include:
+  * We have eliminated the use of callback routines for handling the
+    uncompressed image data.  The application now sees the library as a
+    set of routines that it calls to read or write image data on a
+    scanline-by-scanline basis.
+  * The application image data is represented in a conventional interleaved-
+    pixel format, rather than as a separate array for each color channel.
+    This can save a copying step in many programs.
+  * The handling of compressed data has been cleaned up: the application can
+    supply routines to source or sink the compressed data.  It is possible to
+    suspend processing on source/sink buffer overrun, although this is not
+    supported in all operating modes.
+  * All static state has been eliminated from the library, so that multiple
+    instances of compression or decompression can be active concurrently.
+  * JPEG abbreviated datastream formats are supported, ie, quantization and
+    Huffman tables can be stored separately from the image data.
+  * And not only that, but the documentation of the library has improved
+    considerably!
+
+
+The last widely used release before the version 5 rewrite was version 4A of
+18-Feb-93.  Change logs before that point have been discarded, since they
+are not of much interest after the rewrite.
diff --git a/Utilities/ITK/Utilities/itkjpeg/filelist.doc b/Utilities/ITK/Utilities/itkjpeg/filelist.doc
new file mode 100644
index 0000000000000000000000000000000000000000..9ba88e00325c33ac754e40396e123f0f8af5b3a0
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/filelist.doc
@@ -0,0 +1,239 @@
+IJG JPEG LIBRARY:  FILE LIST
+
+Copyright (C) 1994-1997, Thomas G. Lane.
+This file is part of the Independent JPEG Group's software.
+For conditions of distribution and use, see the accompanying README file.
+
+
+Here is a road map to the files in the IJG JPEG distribution.  The
+distribution includes the JPEG library proper, plus two application
+programs ("cjpeg" and "djpeg") which use the library to convert JPEG
+files to and from some other popular image formats.  A third application
+"jpegtran" uses the library to do lossless conversion between different
+variants of JPEG.  There are also two stand-alone applications,
+"rdjpgcom" and "wrjpgcom".
+
+
+THE JPEG LIBRARY
+================
+
+Include files:
+
+jpeglib.h	JPEG library's exported data and function declarations.
+jconfig.h	Configuration declarations.  Note: this file is not present
+		in the distribution; it is generated during installation.
+jmorecfg.h	Additional configuration declarations; need not be changed
+		for a standard installation.
+jerror.h	Declares JPEG library's error and trace message codes.
+jinclude.h	Central include file used by all IJG .c files to reference
+		system include files.
+jpegint.h	JPEG library's internal data structures.
+jlossls.h	JPEG library's lossless codec data structures.
+jlossy.h	JPEG library's lossy codec structures.
+jchuff.h	Private declarations for Huffman encoder modules.
+jdhuff.h	Private declarations for Huffman decoder modules.
+jdct.h		Private declarations for forward & reverse DCT subsystems.
+jmemsys.h	Private declarations for memory management subsystem.
+jversion.h	Version information.
+
+Applications using the library should include jpeglib.h (which in turn
+includes jconfig.h and jmorecfg.h).  Optionally, jerror.h may be included
+if the application needs to reference individual JPEG error codes.  The
+other include files are intended for internal use and would not normally
+be included by an application program.  (cjpeg/djpeg/etc do use jinclude.h,
+since its function is to improve portability of the whole IJG distribution.
+Most other applications will directly include the system include files they
+want, and hence won't need jinclude.h.)
+
+
+C source code files:
+
+These files contain most of the functions intended to be called directly by
+an application program:
+
+jcapimin.c	Application program interface: core routines for compression.
+jcapistd.c	Application program interface: standard compression.
+jdapimin.c	Application program interface: core routines for decompression.
+jdapistd.c	Application program interface: standard decompression.
+jcomapi.c	Application program interface routines common to compression
+		and decompression.
+jcparam.c	Compression parameter setting helper routines.
+jctrans.c	API and library routines for transcoding compression.
+jdtrans.c	API and library routines for transcoding decompression.
+
+Compression side of the library:
+
+jcinit.c	Initialization: determines which other modules to use.
+jcmaster.c	Master control: setup and inter-pass sequencing logic.
+jcmainct.c	Main buffer controller (preprocessor => JPEG compressor).
+jchuff.c	Codec-independent Huffman entropy encoding routines.
+jcprepct.c	Preprocessor buffer controller.
+jccolor.c	Color space conversion.
+jcsample.c	Downsampling.
+jcmarker.c	JPEG marker writing.
+jdatadst.c	Data destination manager for stdio output.
+
+Lossy (DCT) codec:
+
+jlossy.c	Lossy compressor proper.
+jccoefct.c	Buffer controller for DCT coefficient buffer.
+jcdctmgr.c	DCT manager (DCT implementation selection & control).
+jfdctint.c	Forward DCT using slow-but-accurate integer method.
+jfdctfst.c	Forward DCT using faster, less accurate integer method.
+jfdctflt.c	Forward DCT using floating-point arithmetic.
+jcshuff.c	Huffman entropy coding for sequential JPEG.
+jcphuff.c	Huffman entropy coding for progressive JPEG.
+
+Lossless (spatial) codec:
+
+jclossls.c	Lossless compressor proper.
+jcdiffct.c	Buffer controller for difference buffer.
+jcscale.c	Point transformation.
+jcpred.c	Sample predictor and differencer.
+jclhuff.c	Huffman entropy encoding for lossless JPEG.
+
+Decompression side of the library:
+
+jdmaster.c	Master control: determines which other modules to use.
+jdinput.c	Input controller: controls input processing modules.
+jdmainct.c	Main buffer controller (JPEG decompressor => postprocessor).
+jdhuff.c	Codec-independent Huffman entropy decoding routines.
+jdpostct.c	Postprocessor buffer controller.
+jdmarker.c	JPEG marker reading.
+jdsample.c	Upsampling.
+jdcolor.c	Color space conversion.
+jdmerge.c	Merged upsampling/color conversion (faster, lower quality).
+jquant1.c	One-pass color quantization using a fixed-spacing colormap.
+jquant2.c	Two-pass color quantization using a custom-generated colormap.
+		Also handles one-pass quantization to an externally given map.
+jdatasrc.c	Data source manager for stdio input.
+
+Lossy (DCT) codec:
+
+jdlossy.c	Lossy decompressor proper.
+jdcoefct.c	Buffer controller for DCT coefficient buffer.
+jdshuff.c	Huffman entropy decoding for sequential JPEG.
+jdphuff.c	Huffman entropy decoding for progressive JPEG.
+jddctmgr.c	IDCT manager (IDCT implementation selection & control).
+jidctint.c	Inverse DCT using slow-but-accurate integer method.
+jidctfst.c	Inverse DCT using faster, less accurate integer method.
+jidctflt.c	Inverse DCT using floating-point arithmetic.
+jidctred.c	Inverse DCTs with reduced-size outputs.
+
+Lossless (spatial) codec:
+
+jdlossls.c	Lossless decompressor proper.
+jddiffct.c	Buffer controller for difference buffers.
+jdlhuff.c	Huffman entropy decoding for lossless JPEG.
+jdpred.c	Sample predictor and undifferencer.
+jdscale.c	Point transformation, sample size scaling.
+
+Support files for both compression and decompression:
+
+jerror.c	Standard error handling routines (application replaceable).
+jmemmgr.c	System-independent (more or less) memory management code.
+jcodec.c	Codec-independent utility routines.
+jutils.c	Miscellaneous utility routines.
+
+jmemmgr.c relies on a system-dependent memory management module.  The IJG
+distribution includes the following implementations of the system-dependent
+module:
+
+jmemnobs.c	"No backing store": assumes adequate virtual memory exists.
+jmemansi.c	Makes temporary files with ANSI-standard routine tmpfile().
+jmemname.c	Makes temporary files with program-generated file names.
+jmemdos.c	Custom implementation for MS-DOS (16-bit environment only):
+		can use extended and expanded memory as well as temp files.
+jmemmac.c	Custom implementation for Apple Macintosh.
+
+Exactly one of the system-dependent modules should be configured into an
+installed JPEG library (see install.doc for hints about which one to use).
+On unusual systems you may find it worthwhile to make a special
+system-dependent memory manager.
+
+
+Non-C source code files:
+
+jmemdosa.asm	80x86 assembly code support for jmemdos.c; used only in
+		MS-DOS-specific configurations of the JPEG library.
+
+
+CJPEG/DJPEG/JPEGTRAN
+====================
+
+Include files:
+
+cdjpeg.h	Declarations shared by cjpeg/djpeg/jpegtran modules.
+cderror.h	Additional error and trace message codes for cjpeg et al.
+transupp.h	Declarations for jpegtran support routines in transupp.c.
+
+C source code files:
+
+cjpeg.c		Main program for cjpeg.
+djpeg.c		Main program for djpeg.
+jpegtran.c	Main program for jpegtran.
+cdjpeg.c	Utility routines used by all three programs.
+rdcolmap.c	Code to read a colormap file for djpeg's "-map" switch.
+rdswitch.c	Code to process some of cjpeg's more complex switches.
+		Also used by jpegtran.
+transupp.c	Support code for jpegtran: lossless image manipulations.
+
+Image file reader modules for cjpeg:
+
+rdbmp.c		BMP file input.
+rdgif.c		GIF file input (now just a stub).
+rdppm.c		PPM/PGM file input.
+rdrle.c		Utah RLE file input.
+rdtarga.c	Targa file input.
+
+Image file writer modules for djpeg:
+
+wrbmp.c		BMP file output.
+wrgif.c		GIF file output (a mere shadow of its former self).
+wrppm.c		PPM/PGM file output.
+wrrle.c		Utah RLE file output.
+wrtarga.c	Targa file output.
+
+
+RDJPGCOM/WRJPGCOM
+=================
+
+C source code files:
+
+rdjpgcom.c	Stand-alone rdjpgcom application.
+wrjpgcom.c	Stand-alone wrjpgcom application.
+
+These programs do not depend on the IJG library.  They do use
+jconfig.h and jinclude.h, only to improve portability.
+
+
+ADDITIONAL FILES
+================
+
+Documentation (see README for a guide to the documentation files):
+
+README		Master documentation file.
+*.doc		Other documentation files.
+*.1		Documentation in Unix man page format.
+change.log	Version-to-version change highlights.
+example.c	Sample code for calling JPEG library.
+
+Configuration/installation files and programs (see install.doc for more info):
+
+configure	Unix shell script to perform automatic configuration.
+ltconfig	Support scripts for configure (from GNU libtool).
+ltmain.sh
+config.guess
+config.sub
+install-sh	Install shell script for those Unix systems lacking one.
+ckconfig.c	Program to generate jconfig.h on non-Unix systems.
+jconfig.doc	Template for making jconfig.h by hand.
+makefile.*	Sample makefiles for particular systems.
+jconfig.*	Sample jconfig.h for particular systems.
+ansi2knr.c	De-ANSIfier for pre-ANSI C compilers (courtesy of
+		L. Peter Deutsch and Aladdin Enterprises).
+
+Test files (see install.doc for test procedure):
+
+test*.*		Source and comparison files for confidence test.
+		These are binary image files, NOT text files.
diff --git a/Utilities/ITK/Utilities/itkjpeg/install.doc b/Utilities/ITK/Utilities/itkjpeg/install.doc
new file mode 100644
index 0000000000000000000000000000000000000000..3702b986b6f9bf5c3156a1bd84edbebfdc911b44
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/install.doc
@@ -0,0 +1,1063 @@
+INSTALLATION INSTRUCTIONS for the Independent JPEG Group's JPEG software
+
+Copyright (C) 1991-1998, Thomas G. Lane.
+This file is part of the Independent JPEG Group's software.
+For conditions of distribution and use, see the accompanying README file.
+
+
+This file explains how to configure and install the IJG software.  We have
+tried to make this software extremely portable and flexible, so that it can be
+adapted to almost any environment.  The downside of this decision is that the
+installation process is complicated.  We have provided shortcuts to simplify
+the task on common systems.  But in any case, you will need at least a little
+familiarity with C programming and program build procedures for your system.
+
+If you are only using this software as part of a larger program, the larger
+program's installation procedure may take care of configuring the IJG code.
+For example, Ghostscript's installation script will configure the IJG code.
+You don't need to read this file if you just want to compile Ghostscript.
+
+If you are on a Unix machine, you may not need to read this file at all.
+Try doing
+	./configure
+	make
+	make test
+If that doesn't complain, do
+	make install
+(better do "make -n install" first to see if the makefile will put the files
+where you want them).  Read further if you run into snags or want to customize
+the code for your system.
+
+
+TABLE OF CONTENTS
+-----------------
+
+Before you start
+Configuring the software:
+	using the automatic "configure" script
+	using one of the supplied jconfig and makefile files
+	by hand
+Building the software
+Testing the software
+Installing the software
+Optional stuff
+Optimization
+Hints for specific systems
+
+
+BEFORE YOU START
+================
+
+Before installing the software you must unpack the distributed source code.
+Since you are reading this file, you have probably already succeeded in this
+task.  However, there is a potential for error if you needed to convert the
+files to the local standard text file format (for example, if you are on
+MS-DOS you may have converted LF end-of-line to CR/LF).  You must apply
+such conversion to all the files EXCEPT those whose names begin with "test".
+The test files contain binary data; if you change them in any way then the
+self-test will give bad results.
+
+Please check the last section of this file to see if there are hints for the
+specific machine or compiler you are using.
+
+
+CONFIGURING THE SOFTWARE
+========================
+
+To configure the IJG code for your system, you need to create two files:
+  * jconfig.h: contains values for system-dependent #define symbols.
+  * Makefile: controls the compilation process.
+(On a non-Unix machine, you may create "project files" or some other
+substitute for a Makefile.  jconfig.h is needed in any environment.)
+
+We provide three different ways to generate these files:
+  * On a Unix system, you can just run the "configure" script.
+  * We provide sample jconfig files and makefiles for popular machines;
+    if your machine matches one of the samples, just copy the right sample
+    files to jconfig.h and Makefile.
+  * If all else fails, read the instructions below and make your own files.
+
+
+Configuring the software using the automatic "configure" script
+---------------------------------------------------------------
+
+If you are on a Unix machine, you can just type
+	./configure
+and let the configure script construct appropriate configuration files.
+If you're using "csh" on an old version of System V, you might need to type
+	sh configure
+instead to prevent csh from trying to execute configure itself.
+Expect configure to run for a few minutes, particularly on slower machines;
+it works by compiling a series of test programs.
+
+Configure was created with GNU Autoconf and it follows the usual conventions
+for GNU configure scripts.  It makes a few assumptions that you may want to
+override.  You can do this by providing optional switches to configure:
+
+* If you want to build libjpeg as a shared library, say
+	./configure --enable-shared
+To get both shared and static libraries, say
+	./configure --enable-shared --enable-static
+Note that these switches invoke GNU libtool to take care of system-dependent
+shared library building methods.  If things don't work this way, please try
+running configure without either switch; that should build a static library
+without using libtool.  If that works, your problem is probably with libtool
+not with the IJG code.  libtool is fairly new and doesn't support all flavors
+of Unix yet.  (You might be able to find a newer version of libtool than the
+one included with libjpeg; see ftp.gnu.org.  Report libtool problems to
+bug-libtool@gnu.org.)
+
+* Configure will use gcc (GNU C compiler) if it's available, otherwise cc.
+To force a particular compiler to be selected, use the CC option, for example
+	./configure CC='cc'
+The same method can be used to include any unusual compiler switches.
+For example, on HP-UX you probably want to say
+	./configure CC='cc -Aa'
+to get HP's compiler to run in ANSI mode.
+
+* The default CFLAGS setting is "-O" for non-gcc compilers, "-O2" for gcc.
+You can override this by saying, for example,
+	./configure CFLAGS='-g'
+if you want to compile with debugging support.
+
+* Configure will set up the makefile so that "make install" will install files
+into /usr/local/bin, /usr/local/man, etc.  You can specify an installation
+prefix other than "/usr/local" by giving configure the option "--prefix=PATH".
+
+* If you don't have a lot of swap space, you may need to enable the IJG
+software's internal virtual memory mechanism.  To do this, give the option
+"--enable-maxmem=N" where N is the default maxmemory limit in megabytes.
+This is discussed in more detail under "Selecting a memory manager", below.
+You probably don't need to worry about this on reasonably-sized Unix machines,
+unless you plan to process very large images.
+
+Configure has some other features that are useful if you are cross-compiling
+or working in a network of multiple machine types; but if you need those
+features, you probably already know how to use them.
+
+
+Configuring the software using one of the supplied jconfig and makefile files
+-----------------------------------------------------------------------------
+
+If you have one of these systems, you can just use the provided configuration
+files:
+
+Makefile	jconfig file	System and/or compiler
+
+makefile.manx	jconfig.manx	Amiga, Manx Aztec C
+makefile.sas	jconfig.sas	Amiga, SAS C
+makeproj.mac	jconfig.mac	Apple Macintosh, Metrowerks CodeWarrior
+mak*jpeg.st	jconfig.st	Atari ST/STE/TT, Pure C or Turbo C
+makefile.bcc	jconfig.bcc	MS-DOS or OS/2, Borland C
+makefile.dj	jconfig.dj	MS-DOS, DJGPP (Delorie's port of GNU C)
+makefile.mc6	jconfig.mc6	MS-DOS, Microsoft C (16-bit only)
+makefile.wat	jconfig.wat	MS-DOS, OS/2, or Windows NT, Watcom C
+makefile.vc	jconfig.vc	Windows NT/95, MS Visual C++
+make*.ds	jconfig.vc	Windows NT/95, MS Developer Studio
+makefile.mms	jconfig.vms	Digital VMS, with MMS software
+makefile.vms	jconfig.vms	Digital VMS, without MMS software
+
+Copy the proper jconfig file to jconfig.h and the makefile to Makefile (or
+whatever your system uses as the standard makefile name).  For more info see
+the appropriate system-specific hints section near the end of this file.
+
+
+Configuring the software by hand
+--------------------------------
+
+First, generate a jconfig.h file.  If you are moderately familiar with C,
+the comments in jconfig.doc should be enough information to do this; just
+copy jconfig.doc to jconfig.h and edit it appropriately.  Otherwise, you may
+prefer to use the ckconfig.c program.  You will need to compile and execute
+ckconfig.c by hand --- we hope you know at least enough to do that.
+ckconfig.c may not compile the first try (in fact, the whole idea is for it
+to fail if anything is going to).  If you get compile errors, fix them by
+editing ckconfig.c according to the directions given in ckconfig.c.  Once
+you get it to run, it will write a suitable jconfig.h file, and will also
+print out some advice about which makefile to use.
+
+You may also want to look at the canned jconfig files, if there is one for a
+system similar to yours.
+
+Second, select a makefile and copy it to Makefile (or whatever your system
+uses as the standard makefile name).  The most generic makefiles we provide
+are
+	makefile.ansi:	if your C compiler supports function prototypes
+	makefile.unix:	if not.
+(You have function prototypes if ckconfig.c put "#define HAVE_PROTOTYPES"
+in jconfig.h.)  You may want to start from one of the other makefiles if
+there is one for a system similar to yours.
+
+Look over the selected Makefile and adjust options as needed.  In particular
+you may want to change the CC and CFLAGS definitions.  For instance, if you
+are using GCC, set CC=gcc.  If you had to use any compiler switches to get
+ckconfig.c to work, make sure the same switches are in CFLAGS.
+
+If you are on a system that doesn't use makefiles, you'll need to set up
+project files (or whatever you do use) to compile all the source files and
+link them into executable files cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom.
+See the file lists in any of the makefiles to find out which files go into
+each program.  Note that the provided makefiles all make a "library" file
+libjpeg first, but you don't have to do that if you don't want to; the file
+lists identify which source files are actually needed for compression,
+decompression, or both.  As a last resort, you can make a batch script that
+just compiles everything and links it all together; makefile.vms is an example
+of this (it's for VMS systems that have no make-like utility).
+
+Here are comments about some specific configuration decisions you'll
+need to make:
+
+Command line style
+------------------
+
+These programs can use a Unix-like command line style which supports
+redirection and piping, like this:
+	cjpeg inputfile >outputfile
+	cjpeg <inputfile >outputfile
+	source program | cjpeg >outputfile
+The simpler "two file" command line style is just
+	cjpeg inputfile outputfile
+You may prefer the two-file style, particularly if you don't have pipes.
+
+You MUST use two-file style on any system that doesn't cope well with binary
+data fed through stdin/stdout; this is true for some MS-DOS compilers, for
+example.  If you're not on a Unix system, it's safest to assume you need
+two-file style.  (But if your compiler provides either the Posix-standard
+fdopen() library routine or a Microsoft-compatible setmode() routine, you
+can safely use the Unix command line style, by defining USE_FDOPEN or
+USE_SETMODE respectively.)
+
+To use the two-file style, make jconfig.h say "#define TWO_FILE_COMMANDLINE".
+
+Selecting a memory manager
+--------------------------
+
+The IJG code is capable of working on images that are too big to fit in main
+memory; data is swapped out to temporary files as necessary.  However, the
+code to do this is rather system-dependent.  We provide five different
+memory managers:
+
+* jmemansi.c	This version uses the ANSI-standard library routine tmpfile(),
+		which not all non-ANSI systems have.  On some systems
+		tmpfile() may put the temporary file in a non-optimal
+		location; if you don't like what it does, use jmemname.c.
+
+* jmemname.c	This version creates named temporary files.  For anything
+		except a Unix machine, you'll need to configure the
+		select_file_name() routine appropriately; see the comments
+		near the head of jmemname.c.  If you use this version, define
+		NEED_SIGNAL_CATCHER in jconfig.h to make sure the temp files
+		are removed if the program is aborted.
+
+* jmemnobs.c	(That stands for No Backing Store :-).)  This will compile on
+		almost any system, but it assumes you have enough main memory
+		or virtual memory to hold the biggest images you work with.
+
+* jmemdos.c	This should be used with most 16-bit MS-DOS compilers.
+		See the system-specific notes about MS-DOS for more info.
+		IMPORTANT: if you use this, define USE_MSDOS_MEMMGR in
+		jconfig.h, and include the assembly file jmemdosa.asm in the
+		programs.  The supplied makefiles and jconfig files for
+		16-bit MS-DOS compilers already do both.
+
+* jmemmac.c	Custom version for Apple Macintosh; see the system-specific
+		notes for Macintosh for more info.
+
+To use a particular memory manager, change the SYSDEPMEM variable in your
+makefile to equal the corresponding object file name (for example, jmemansi.o
+or jmemansi.obj for jmemansi.c).
+
+If you have plenty of (real or virtual) main memory, just use jmemnobs.c.
+"Plenty" means about ten bytes for every pixel in the largest images
+you plan to process, so a lot of systems don't meet this criterion.
+If yours doesn't, try jmemansi.c first.  If that doesn't compile, you'll have
+to use jmemname.c; be sure to adjust select_file_name() for local conditions.
+You may also need to change unlink() to remove() in close_backing_store().
+
+Except with jmemnobs.c or jmemmac.c, you need to adjust the DEFAULT_MAX_MEM
+setting to a reasonable value for your system (either by adding a #define for
+DEFAULT_MAX_MEM to jconfig.h, or by adding a -D switch to the Makefile).
+This value limits the amount of data space the program will attempt to
+allocate.  Code and static data space isn't counted, so the actual memory
+needs for cjpeg or djpeg are typically 100 to 150Kb more than the max-memory
+setting.  Larger max-memory settings reduce the amount of I/O needed to
+process a large image, but too large a value can result in "insufficient
+memory" failures.  On most Unix machines (and other systems with virtual
+memory), just set DEFAULT_MAX_MEM to several million and forget it.  At the
+other end of the spectrum, for MS-DOS machines you probably can't go much
+above 300K to 400K.  (On MS-DOS the value refers to conventional memory only.
+Extended/expanded memory is handled separately by jmemdos.c.)
+
+
+BUILDING THE SOFTWARE
+=====================
+
+Now you should be able to compile the software.  Just say "make" (or
+whatever's necessary to start the compilation).  Have a cup of coffee.
+
+Here are some things that could go wrong:
+
+If your compiler complains about undefined structures, you should be able to
+shut it up by putting "#define INCOMPLETE_TYPES_BROKEN" in jconfig.h.
+
+If you have trouble with missing system include files or inclusion of the
+wrong ones, read jinclude.h.  This shouldn't happen if you used configure
+or ckconfig.c to set up jconfig.h.
+
+There are a fair number of routines that do not use all of their parameters;
+some compilers will issue warnings about this, which you can ignore.  There
+are also a few configuration checks that may give "unreachable code" warnings.
+Any other warning deserves investigation.
+
+If you don't have a getenv() library routine, define NO_GETENV.
+
+Also see the system-specific hints, below.
+
+
+TESTING THE SOFTWARE
+====================
+
+As a quick test of functionality we've included a small sample image in
+several forms:
+	testorig.jpg	Starting point for the djpeg tests.
+	testimg.ppm	The output of djpeg testorig.jpg
+	testimg.bmp	The output of djpeg -bmp -colors 256 testorig.jpg
+	testimg.jpg	The output of cjpeg testimg.ppm
+	testprog.jpg	Progressive-mode equivalent of testorig.jpg.
+	testimgp.jpg	The output of cjpeg -progressive -optimize testimg.ppm
+(The first- and second-generation .jpg files aren't identical since JPEG is
+lossy.)  If you can generate duplicates of the testimg* files then you
+probably have working programs.
+
+With most of the makefiles, "make test" will perform the necessary
+comparisons.
+
+If you're using a makefile that doesn't provide the test option, run djpeg
+and cjpeg by hand and compare the output files to testimg* with whatever
+binary file comparison tool you have.  The files should be bit-for-bit
+identical.
+
+If the programs complain "MAX_ALLOC_CHUNK is wrong, please fix", then you
+need to reduce MAX_ALLOC_CHUNK to a value that fits in type size_t.
+Try adding "#define MAX_ALLOC_CHUNK 65520L" to jconfig.h.  A less likely
+configuration error is "ALIGN_TYPE is wrong, please fix": defining ALIGN_TYPE
+as long should take care of that one.
+
+If the cjpeg test run fails with "Missing Huffman code table entry", it's a
+good bet that you needed to define RIGHT_SHIFT_IS_UNSIGNED.  Go back to the
+configuration step and run ckconfig.c.  (This is a good plan for any other
+test failure, too.)
+
+If you are using Unix (one-file) command line style on a non-Unix system,
+it's a good idea to check that binary I/O through stdin/stdout actually
+works.  You should get the same results from "djpeg <testorig.jpg >out.ppm"
+as from "djpeg -outfile out.ppm testorig.jpg".  Note that the makefiles all
+use the latter style and therefore do not exercise stdin/stdout!  If this
+check fails, try recompiling with USE_SETMODE or USE_FDOPEN defined.
+If it still doesn't work, better use two-file style.
+
+If you chose a memory manager other than jmemnobs.c, you should test that
+temporary-file usage works.  Try "djpeg -bmp -colors 256 -max 0 testorig.jpg"
+and make sure its output matches testimg.bmp.  If you have any really large
+images handy, try compressing them with -optimize and/or decompressing with
+-colors 256 to make sure your DEFAULT_MAX_MEM setting is not too large.
+
+NOTE: this is far from an exhaustive test of the JPEG software; some modules,
+such as 1-pass color quantization, are not exercised at all.  It's just a
+quick test to give you some confidence that you haven't missed something
+major.
+
+
+INSTALLING THE SOFTWARE
+=======================
+
+Once you're done with the above steps, you can install the software by
+copying the executable files (cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom)
+to wherever you normally install programs.  On Unix systems, you'll also want
+to put the man pages (cjpeg.1, djpeg.1, jpegtran.1, rdjpgcom.1, wrjpgcom.1)
+in the man-page directory.  The pre-fab makefiles don't support this step
+since there's such a wide variety of installation procedures on different
+systems.
+
+If you generated a Makefile with the "configure" script, you can just say
+	make install
+to install the programs and their man pages into the standard places.
+(You'll probably need to be root to do this.)  We recommend first saying
+	make -n install
+to see where configure thought the files should go.  You may need to edit
+the Makefile, particularly if your system's conventions for man page
+filenames don't match what configure expects.
+
+If you want to install the IJG library itself, for use in compiling other
+programs besides ours, then you need to put the four include files
+	jpeglib.h jerror.h jconfig.h jmorecfg.h
+into your include-file directory, and put the library file libjpeg.a
+(extension may vary depending on system) wherever library files go.
+If you generated a Makefile with "configure", it will do what it thinks
+is the right thing if you say
+	make install-lib
+
+
+OPTIONAL STUFF
+==============
+
+Progress monitor:
+
+If you like, you can #define PROGRESS_REPORT (in jconfig.h) to enable display
+of percent-done progress reports.  The routine provided in cdjpeg.c merely
+prints percentages to stderr, but you can customize it to do something
+fancier.
+
+Utah RLE file format support:
+
+We distribute the software with support for RLE image files (Utah Raster
+Toolkit format) disabled, because the RLE support won't compile without the
+Utah library.  If you have URT version 3.1 or later, you can enable RLE
+support as follows:
+	1.  #define RLE_SUPPORTED in jconfig.h.
+	2.  Add a -I option to CFLAGS in the Makefile for the directory
+	    containing the URT .h files (typically the "include"
+	    subdirectory of the URT distribution).
+	3.  Add -L... -lrle to LDLIBS in the Makefile, where ... specifies
+	    the directory containing the URT "librle.a" file (typically the
+	    "lib" subdirectory of the URT distribution).
+
+Support for 12-bit-deep pixel data:
+
+The JPEG standard allows either 8-bit or 12-bit data precision.  (For color,
+this means 8 or 12 bits per channel, of course.)  If you need to work with
+deeper than 8-bit data, you can compile the IJG code for 12-bit operation.
+To do so:
+  1. In jmorecfg.h, define BITS_IN_JSAMPLE as 12 rather than 8.
+  2. In jconfig.h, undefine BMP_SUPPORTED, RLE_SUPPORTED, and TARGA_SUPPORTED,
+     because the code for those formats doesn't handle 12-bit data and won't
+     even compile.  (The PPM code does work, as explained below.  The GIF
+     code works too; it scales 8-bit GIF data to and from 12-bit depth
+     automatically.)
+  3. Compile.  Don't expect "make test" to pass, since the supplied test
+     files are for 8-bit data.
+
+Currently, 12-bit support does not work on 16-bit-int machines.
+
+Note that a 12-bit version will not read 8-bit JPEG files, nor vice versa;
+so you'll want to keep around a regular 8-bit compilation as well.
+(Run-time selection of data depth, to allow a single copy that does both,
+is possible but would probably slow things down considerably; it's very low
+on our to-do list.)
+
+The PPM reader (rdppm.c) can read 12-bit data from either text-format or
+binary-format PPM and PGM files.  Binary-format PPM/PGM files which have a
+maxval greater than 255 are assumed to use 2 bytes per sample, LSB first
+(little-endian order).  As of early 1995, 2-byte binary format is not
+officially supported by the PBMPLUS library, but it is expected that a
+future release of PBMPLUS will support it.  Note that the PPM reader will
+read files of any maxval regardless of the BITS_IN_JSAMPLE setting; incoming
+data is automatically rescaled to either maxval=255 or maxval=4095 as
+appropriate for the cjpeg bit depth.
+
+The PPM writer (wrppm.c) will normally write 2-byte binary PPM or PGM
+format, maxval 4095, when compiled with BITS_IN_JSAMPLE=12.  Since this
+format is not yet widely supported, you can disable it by compiling wrppm.c
+with PPM_NORAWWORD defined; then the data is scaled down to 8 bits to make a
+standard 1-byte/sample PPM or PGM file.  (Yes, this means still another copy
+of djpeg to keep around.  But hopefully you won't need it for very long.
+Poskanzer's supposed to get that new PBMPLUS release out Real Soon Now.)
+
+Of course, if you are working with 12-bit data, you probably have it stored
+in some other, nonstandard format.  In that case you'll probably want to
+write your own I/O modules to read and write your format.
+
+Note that a 12-bit version of cjpeg always runs in "-optimize" mode, in
+order to generate valid Huffman tables.  This is necessary because our
+default Huffman tables only cover 8-bit data.
+
+Removing code:
+
+If you need to make a smaller version of the JPEG software, some optional
+functions can be removed at compile time.  See the xxx_SUPPORTED #defines in
+jconfig.h and jmorecfg.h.  If at all possible, we recommend that you leave in
+decoder support for all valid JPEG files, to ensure that you can read anyone's
+output.  Taking out support for image file formats that you don't use is the
+most painless way to make the programs smaller.  Another possibility is to
+remove some of the DCT methods: in particular, the "IFAST" method may not be
+enough faster than the others to be worth keeping on your machine.  (If you
+do remove ISLOW or IFAST, be sure to redefine JDCT_DEFAULT or JDCT_FASTEST
+to a supported method, by adding a #define in jconfig.h.)
+
+
+OPTIMIZATION
+============
+
+Unless you own a Cray, you'll probably be interested in making the JPEG
+software go as fast as possible.  This section covers some machine-dependent
+optimizations you may want to try.  We suggest that before trying any of
+this, you first get the basic installation to pass the self-test step.
+Repeat the self-test after any optimization to make sure that you haven't
+broken anything.
+
+The integer DCT routines perform a lot of multiplications.  These
+multiplications must yield 32-bit results, but none of their input values
+are more than 16 bits wide.  On many machines, notably the 680x0 and 80x86
+CPUs, a 16x16=>32 bit multiply instruction is faster than a full 32x32=>32
+bit multiply.  Unfortunately there is no portable way to specify such a
+multiplication in C, but some compilers can generate one when you use the
+right combination of casts.  See the MULTIPLYxxx macro definitions in
+jdct.h.  If your compiler makes "int" be 32 bits and "short" be 16 bits,
+defining SHORTxSHORT_32 is fairly likely to work.  When experimenting with
+alternate definitions, be sure to test not only whether the code still works
+(use the self-test), but also whether it is actually faster --- on some
+compilers, alternate definitions may compute the right answer, yet be slower
+than the default.  Timing cjpeg on a large PGM (grayscale) input file is the
+best way to check this, as the DCT will be the largest fraction of the runtime
+in that mode.  (Note: some of the distributed compiler-specific jconfig files
+already contain #define switches to select appropriate MULTIPLYxxx
+definitions.)
+
+If your machine has sufficiently fast floating point hardware, you may find
+that the float DCT method is faster than the integer DCT methods, even
+after tweaking the integer multiply macros.  In that case you may want to
+make the float DCT be the default method.  (The only objection to this is
+that float DCT results may vary slightly across machines.)  To do that, add
+"#define JDCT_DEFAULT JDCT_FLOAT" to jconfig.h.  Even if you don't change
+the default, you should redefine JDCT_FASTEST, which is the method selected
+by djpeg's -fast switch.  Don't forget to update the documentation files
+(usage.doc and/or cjpeg.1, djpeg.1) to agree with what you've done.
+
+If access to "short" arrays is slow on your machine, it may be a win to
+define type JCOEF as int rather than short.  This will cost a good deal of
+memory though, particularly in some multi-pass modes, so don't do it unless
+you have memory to burn and short is REALLY slow.
+
+If your compiler can compile function calls in-line, make sure the INLINE
+macro in jmorecfg.h is defined as the keyword that marks a function
+inline-able.  Some compilers have a switch that tells the compiler to inline
+any function it thinks is profitable (e.g., -finline-functions for gcc).
+Enabling such a switch is likely to make the compiled code bigger but faster.
+
+In general, it's worth trying the maximum optimization level of your compiler,
+and experimenting with any optional optimizations such as loop unrolling.
+(Unfortunately, far too many compilers have optimizer bugs ... be prepared to
+back off if the code fails self-test.)  If you do any experimentation along
+these lines, please report the optimal settings to jpeg-info@uunet.uu.net so
+we can mention them in future releases.  Be sure to specify your machine and
+compiler version.
+
+
+HINTS FOR SPECIFIC SYSTEMS
+==========================
+
+We welcome reports on changes needed for systems not mentioned here.  Submit
+'em to jpeg-info@uunet.uu.net.  Also, if configure or ckconfig.c is wrong
+about how to configure the JPEG software for your system, please let us know.
+
+
+Acorn RISC OS:
+
+(Thanks to Simon Middleton for these hints on compiling with Desktop C.)
+After renaming the files according to Acorn conventions, take a copy of
+makefile.ansi, change all occurrences of 'libjpeg.a' to 'libjpeg.o' and
+change these definitions as indicated:
+
+CFLAGS= -throwback -IC: -Wn
+LDLIBS=C:o.Stubs
+SYSDEPMEM=jmemansi.o
+LN=Link
+AR=LibFile -c -o
+
+Also add a new line '.c.o:; $(cc) $< $(cflags) -c -o $@'.  Remove the
+lines '$(RM) libjpeg.o' and '$(AR2) libjpeg.o' and the 'jconfig.h'
+dependency section.
+
+Copy jconfig.doc to jconfig.h.  Edit jconfig.h to define TWO_FILE_COMMANDLINE
+and CHAR_IS_UNSIGNED.
+
+Run the makefile using !AMU not !Make.  If you want to use the 'clean' and
+'test' makefile entries then you will have to fiddle with the syntax a bit
+and rename the test files.
+
+
+Amiga:
+
+SAS C 6.50 reportedly is too buggy to compile the IJG code properly.
+A patch to update to 6.51 is available from SAS or AmiNet FTP sites.
+
+The supplied config files are set up to use jmemname.c as the memory
+manager, with temporary files being created on the device named by
+"JPEGTMP:".
+
+
+Atari ST/STE/TT:
+ 
+Copy the project files makcjpeg.st, makdjpeg.st, maktjpeg.st, and makljpeg.st
+to cjpeg.prj, djpeg.prj, jpegtran.prj, and libjpeg.prj respectively.  The
+project files should work as-is with Pure C.  For Turbo C, change library
+filenames "pc..." to "tc..." in each project file.  Note that libjpeg.prj
+selects jmemansi.c as the recommended memory manager.  You'll probably want to
+adjust the DEFAULT_MAX_MEM setting --- you want it to be a couple hundred K
+less than your normal free memory.  Put "#define DEFAULT_MAX_MEM nnnn" into
+jconfig.h to do this.
+
+To use the 68881/68882 coprocessor for the floating point DCT, add the
+compiler option "-8" to the project files and replace pcfltlib.lib with
+pc881lib.lib in cjpeg.prj and djpeg.prj.  Or if you don't have a
+coprocessor, you may prefer to remove the float DCT code by undefining
+DCT_FLOAT_SUPPORTED in jmorecfg.h (since without a coprocessor, the float
+code will be too slow to be useful).  In that case, you can delete
+pcfltlib.lib from the project files.
+
+Note that you must make libjpeg.lib before making cjpeg.ttp, djpeg.ttp,
+or jpegtran.ttp.  You'll have to perform the self-test by hand.
+
+We haven't bothered to include project files for rdjpgcom and wrjpgcom.
+Those source files should just be compiled by themselves; they don't
+depend on the JPEG library.
+
+There is a bug in some older versions of the Turbo C library which causes the
+space used by temporary files created with "tmpfile()" not to be freed after
+an abnormal program exit.  If you check your disk afterwards, you will find
+cluster chains that are allocated but not used by a file.  This should not
+happen in cjpeg/djpeg/jpegtran, since we enable a signal catcher to explicitly
+close temp files before exiting.  But if you use the JPEG library with your
+own code, be sure to supply a signal catcher, or else use a different
+system-dependent memory manager.
+
+
+Cray:
+
+Should you be so fortunate as to be running JPEG on a Cray YMP, there is a
+compiler bug in old versions of Cray's Standard C (prior to 3.1).  If you
+still have an old compiler, you'll need to insert a line reading
+"#pragma novector" just before the loop	
+    for (i = 1; i <= (int) htbl->bits[l]; i++)
+      huffsize[p++] = (char) l;
+in fix_huff_tbl (in V5beta1, line 204 of jchuff.c and line 176 of jdhuff.c).
+[This bug may or may not still occur with the current IJG code, but it's
+probably a dead issue anyway...]
+
+
+HP-UX:
+
+If you have HP-UX 7.05 or later with the "software development" C compiler,
+you should run the compiler in ANSI mode.  If using the configure script,
+say
+	./configure CC='cc -Aa'
+(or -Ae if you prefer).  If configuring by hand, use makefile.ansi and add
+"-Aa" to the CFLAGS line in the makefile.
+
+If you have a pre-7.05 system, or if you are using the non-ANSI C compiler
+delivered with a minimum HP-UX system, then you must use makefile.unix
+(and do NOT add -Aa); or just run configure without the CC option.
+
+On HP 9000 series 800 machines, the HP C compiler is buggy in revisions prior
+to A.08.07.  If you get complaints about "not a typedef name", you'll have to
+use makefile.unix, or run configure without the CC option.
+
+
+Macintosh, generic comments:
+
+The supplied user-interface files (cjpeg.c, djpeg.c, etc) are set up to
+provide a Unix-style command line interface.  You can use this interface on
+the Mac by means of the ccommand() library routine provided by Metrowerks
+CodeWarrior or Think C.  This is only appropriate for testing the library,
+however; to make a user-friendly equivalent of cjpeg/djpeg you'd really want
+to develop a Mac-style user interface.  There isn't a complete example
+available at the moment, but there are some helpful starting points:
+1. Sam Bushell's free "To JPEG" applet provides drag-and-drop conversion to
+JPEG under System 7 and later.  This only illustrates how to use the
+compression half of the library, but it does a very nice job of that part.
+The CodeWarrior source code is available from http://www.pobox.com/~jsam.
+2. Jim Brunner prepared a Mac-style user interface for both compression and
+decompression.  Unfortunately, it hasn't been updated since IJG v4, and
+the library's API has changed considerably since then.  Still it may be of
+some help, particularly as a guide to compiling the IJG code under Think C.
+Jim's code is available from the Info-Mac archives, at sumex-aim.stanford.edu
+or mirrors thereof; see file /info-mac/dev/src/jpeg-convert-c.hqx.
+
+jmemmac.c is the recommended memory manager back end for Macintosh.  It uses
+NewPtr/DisposePtr instead of malloc/free, and has a Mac-specific
+implementation of jpeg_mem_available().  It also creates temporary files that
+follow Mac conventions.  (That part of the code relies on System-7-or-later OS
+functions.  See the comments in jmemmac.c if you need to run it on System 6.)
+NOTE that USE_MAC_MEMMGR must be defined in jconfig.h to use jmemmac.c.
+
+You can also use jmemnobs.c, if you don't care about handling images larger
+than available memory.  If you use any memory manager back end other than
+jmemmac.c, we recommend replacing "malloc" and "free" by "NewPtr" and
+"DisposePtr", because Mac C libraries often have peculiar implementations of
+malloc/free.  (For instance, free() may not return the freed space to the
+Mac Memory Manager.  This is undesirable for the IJG code because jmemmgr.c
+already clumps space requests.)
+
+
+Macintosh, Metrowerks CodeWarrior:
+
+The Unix-command-line-style interface can be used by defining USE_CCOMMAND.
+You'll also need to define TWO_FILE_COMMANDLINE to avoid stdin/stdout.
+This means that when using the cjpeg/djpeg programs, you'll have to type the
+input and output file names in the "Arguments" text-edit box, rather than
+using the file radio buttons.  (Perhaps USE_FDOPEN or USE_SETMODE would
+eliminate the problem, but I haven't heard from anyone who's tried it.)
+
+On 680x0 Macs, Metrowerks defines type "double" as a 10-byte IEEE extended
+float.  jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power
+of 2.  Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint.
+
+The supplied configuration file jconfig.mac can be used for your jconfig.h;
+it includes all the recommended symbol definitions.  If you have AppleScript
+installed, you can run the supplied script makeproj.mac to create CodeWarrior
+project files for the library and the testbed applications, then build the
+library and applications.  (Thanks to Dan Sears and Don Agro for this nifty
+hack, which saves us from trying to maintain CodeWarrior project files as part
+of the IJG distribution...)
+
+
+Macintosh, Think C:
+
+The documentation in Jim Brunner's "JPEG Convert" source code (see above)
+includes detailed build instructions for Think C; it's probably somewhat
+out of date for the current release, but may be helpful.
+
+If you want to build the minimal command line version, proceed as follows.
+You'll have to prepare project files for the programs; we don't include any
+in the distribution since they are not text files.  Use the file lists in
+any of the supplied makefiles as a guide.  Also add the ANSI and Unix C
+libraries in a separate segment.  You may need to divide the JPEG files into
+more than one segment; we recommend dividing compression and decompression
+modules.  Define USE_CCOMMAND in jconfig.h so that the ccommand() routine is
+called.  You must also define TWO_FILE_COMMANDLINE because stdin/stdout
+don't handle binary data correctly.
+
+On 680x0 Macs, Think C defines type "double" as a 12-byte IEEE extended float.
+jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power of 2.
+Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint.
+
+jconfig.mac should work as a jconfig.h configuration file for Think C,
+but the makeproj.mac AppleScript script is specific to CodeWarrior.  Sorry.
+
+
+MIPS R3000:
+
+MIPS's cc version 1.31 has a rather nasty optimization bug.  Don't use -O
+if you have that compiler version.  (Use "cc -V" to check the version.)
+Note that the R3000 chip is found in workstations from DEC and others.
+
+
+MS-DOS, generic comments for 16-bit compilers:
+
+The IJG code is designed to work well in 80x86 "small" or "medium" memory
+models (i.e., data pointers are 16 bits unless explicitly declared "far";
+code pointers can be either size).  You may be able to use small model to
+compile cjpeg or djpeg by itself, but you will probably have to use medium
+model for any larger application.  This won't make much difference in
+performance.  You *will* take a noticeable performance hit if you use a
+large-data memory model, and you should avoid "huge" model if at all
+possible.  Be sure that NEED_FAR_POINTERS is defined in jconfig.h if you use
+a small-data memory model; be sure it is NOT defined if you use a large-data
+model.  (The supplied makefiles and jconfig files for Borland and Microsoft C
+compile in medium model and define NEED_FAR_POINTERS.)
+
+The DOS-specific memory manager, jmemdos.c, should be used if possible.
+It needs some assembly-code routines which are in jmemdosa.asm; make sure
+your makefile assembles that file and includes it in the library.  If you
+don't have a suitable assembler, you can get pre-assembled object files for
+jmemdosa by FTP from ftp.uu.net:/graphics/jpeg/jdosaobj.zip.  (DOS-oriented
+distributions of the IJG source code often include these object files.)
+
+When using jmemdos.c, jconfig.h must define USE_MSDOS_MEMMGR and must set
+MAX_ALLOC_CHUNK to less than 64K (65520L is a typical value).  If your
+C library's far-heap malloc() can't allocate blocks that large, reduce
+MAX_ALLOC_CHUNK to whatever it can handle.
+
+If you can't use jmemdos.c for some reason --- for example, because you
+don't have an assembler to assemble jmemdosa.asm --- you'll have to fall
+back to jmemansi.c or jmemname.c.  You'll probably still need to set
+MAX_ALLOC_CHUNK in jconfig.h, because most DOS C libraries won't malloc()
+more than 64K at a time.  IMPORTANT: if you use jmemansi.c or jmemname.c,
+you will have to compile in a large-data memory model in order to get the
+right stdio library.  Too bad.
+
+wrjpgcom needs to be compiled in large model, because it malloc()s a 64KB
+work area to hold the comment text.  If your C library's malloc can't
+handle that, reduce MAX_COM_LENGTH as necessary in wrjpgcom.c.
+
+Most MS-DOS compilers treat stdin/stdout as text files, so you must use
+two-file command line style.  But if your compiler has either fdopen() or
+setmode(), you can use one-file style if you like.  To do this, define
+USE_SETMODE or USE_FDOPEN so that stdin/stdout will be set to binary mode.
+(USE_SETMODE seems to work with more DOS compilers than USE_FDOPEN.)  You
+should test that I/O through stdin/stdout produces the same results as I/O
+to explicitly named files... the "make test" procedures in the supplied
+makefiles do NOT use stdin/stdout.
+
+
+MS-DOS, generic comments for 32-bit compilers:
+
+None of the above comments about memory models apply if you are using a
+32-bit flat-memory-space environment, such as DJGPP or Watcom C.  (And you
+should use one if you have it, as performance will be much better than
+8086-compatible code!)  For flat-memory-space compilers, do NOT define
+NEED_FAR_POINTERS, and do NOT use jmemdos.c.  Use jmemnobs.c if the
+environment supplies adequate virtual memory, otherwise use jmemansi.c or
+jmemname.c.
+
+You'll still need to be careful about binary I/O through stdin/stdout.
+See the last paragraph of the previous section.
+
+
+MS-DOS, Borland C:
+
+Be sure to convert all the source files to DOS text format (CR/LF newlines).
+Although Borland C will often work OK with unmodified Unix (LF newlines)
+source files, sometimes it will give bogus compile errors.
+"Illegal character '#'" is the most common such error.  (This is true with
+Borland C 3.1, but perhaps is fixed in newer releases.)
+
+If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE.
+jconfig.bcc already includes #define USE_SETMODE to make this work.
+(fdopen does not work correctly.)
+
+
+MS-DOS, Microsoft C:
+
+makefile.mc6 works with Microsoft C, DOS Visual C++, etc.  It should only
+be used if you want to build a 16-bit (small or medium memory model) program.
+
+If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE.
+jconfig.mc6 already includes #define USE_SETMODE to make this work.
+(fdopen does not work correctly.)
+
+Note that this makefile assumes that the working copy of itself is called
+"makefile".  If you want to call it something else, say "makefile.mak",
+be sure to adjust the dependency line that reads "$(RFILE) : makefile".
+Otherwise the make will fail because it doesn't know how to create "makefile".
+Worse, some releases of Microsoft's make utilities give an incorrect error
+message in this situation.
+
+Old versions of MS C fail with an "out of macro expansion space" error
+because they can't cope with the macro TRACEMS8 (defined in jerror.h).
+If this happens to you, the easiest solution is to change TRACEMS8 to
+expand to nothing.  You'll lose the ability to dump out JPEG coefficient
+tables with djpeg -debug -debug, but at least you can compile.
+
+Original MS C 6.0 is very buggy; it compiles incorrect code unless you turn
+off optimization entirely (remove -O from CFLAGS).  6.00A is better, but it
+still generates bad code if you enable loop optimizations (-Ol or -Ox).
+
+MS C 8.0 crashes when compiling jquant1.c with optimization switch /Oo ...
+which is on by default.  To work around this bug, compile that one file
+with /Oo-.
+
+
+Microsoft Windows (all versions), generic comments:
+
+Some Windows system include files define typedef boolean as "unsigned char".
+The IJG code also defines typedef boolean, but we make it "int" by default.
+This doesn't affect the IJG programs because we don't import those Windows
+include files.  But if you use the JPEG library in your own program, and some
+of your program's files import one definition of boolean while some import the
+other, you can get all sorts of mysterious problems.  A good preventive step
+is to make the IJG library use "unsigned char" for boolean.  To do that,
+add something like this to your jconfig.h file:
+	/* Define "boolean" as unsigned char, not int, per Windows custom */
+	#ifndef __RPCNDR_H__	/* don't conflict if rpcndr.h already read */
+	typedef unsigned char boolean;
+	#endif
+	#define HAVE_BOOLEAN	/* prevent jmorecfg.h from redefining it */
+(This is already in jconfig.vc, by the way.)
+
+windef.h contains the declarations
+	#define far
+	#define FAR far
+Since jmorecfg.h tries to define FAR as empty, you may get a compiler
+warning if you include both jpeglib.h and windef.h (which windows.h
+includes).  To suppress the warning, you can put "#ifndef FAR"/"#endif"
+around the line "#define FAR" in jmorecfg.h.
+
+When using the library in a Windows application, you will almost certainly
+want to modify or replace the error handler module jerror.c, since our
+default error handler does a couple of inappropriate things:
+  1. it tries to write error and warning messages on stderr;
+  2. in event of a fatal error, it exits by calling exit().
+
+A simple stopgap solution for problem 1 is to replace the line
+	fprintf(stderr, "%s\n", buffer);
+(in output_message in jerror.c) with
+	MessageBox(GetActiveWindow(),buffer,"JPEG Error",MB_OK|MB_ICONERROR);
+It's highly recommended that you at least do that much, since otherwise
+error messages will disappear into nowhere.  (Beginning with IJG v6b, this
+code is already present in jerror.c; just define USE_WINDOWS_MESSAGEBOX in
+jconfig.h to enable it.)
+
+The proper solution for problem 2 is to return control to your calling
+application after a library error.  This can be done with the setjmp/longjmp
+technique discussed in libjpeg.doc and illustrated in example.c.  (NOTE:
+some older Windows C compilers provide versions of setjmp/longjmp that
+don't actually work under Windows.  You may need to use the Windows system
+functions Catch and Throw instead.)
+
+The recommended memory manager under Windows is jmemnobs.c; in other words,
+let Windows do any virtual memory management needed.  You should NOT use
+jmemdos.c nor jmemdosa.asm under Windows.
+
+For Windows 3.1, we recommend compiling in medium or large memory model;
+for newer Windows versions, use a 32-bit flat memory model.  (See the MS-DOS
+sections above for more info about memory models.)  In the 16-bit memory
+models only, you'll need to put
+	#define MAX_ALLOC_CHUNK 65520L	/* Maximum request to malloc() */
+into jconfig.h to limit allocation chunks to 64Kb.  (Without that, you'd
+have to use huge memory model, which slows things down unnecessarily.)
+jmemnobs.c works without modification in large or flat memory models, but to
+use medium model, you need to modify its jpeg_get_large and jpeg_free_large
+routines to allocate far memory.  In any case, you might like to replace
+its calls to malloc and free with direct calls on Windows memory allocation
+functions.
+
+You may also want to modify jdatasrc.c and jdatadst.c to use Windows file
+operations rather than fread/fwrite.  This is only necessary if your C
+compiler doesn't provide a competent implementation of C stdio functions.
+
+You might want to tweak the RGB_xxx macros in jmorecfg.h so that the library
+will accept or deliver color pixels in BGR sample order, not RGB; BGR order
+is usually more convenient under Windows.  Note that this change will break
+the sample applications cjpeg/djpeg, but the library itself works fine.
+
+
+Many people want to convert the IJG library into a DLL.  This is reasonably
+straightforward, but watch out for the following:
+
+  1. Don't try to compile as a DLL in small or medium memory model; use
+large model, or even better, 32-bit flat model.  Many places in the IJG code
+assume the address of a local variable is an ordinary (not FAR) pointer;
+that isn't true in a medium-model DLL.
+
+  2. Microsoft C cannot pass file pointers between applications and DLLs.
+(See Microsoft Knowledge Base, PSS ID Number Q50336.)  So jdatasrc.c and
+jdatadst.c don't work if you open a file in your application and then pass
+the pointer to the DLL.  One workaround is to make jdatasrc.c/jdatadst.c
+part of your main application rather than part of the DLL.
+
+  3. You'll probably need to modify the macros GLOBAL() and EXTERN() to
+attach suitable linkage keywords to the exported routine names.  Similarly,
+you'll want to modify METHODDEF() and JMETHOD() to ensure function pointers
+are declared in a way that lets application routines be called back through
+the function pointers.  These macros are in jmorecfg.h.  Typical definitions
+for a 16-bit DLL are:
+	#define GLOBAL(type)		type _far _pascal _loadds _export
+	#define EXTERN(type)		extern type _far _pascal _loadds
+	#define METHODDEF(type)		static type _far _pascal
+	#define JMETHOD(type,methodname,arglist)  \
+		type (_far _pascal *methodname) arglist
+For a 32-bit DLL you may want something like
+	#define GLOBAL(type)		__declspec(dllexport) type
+	#define EXTERN(type)		extern __declspec(dllexport) type
+Although not all the GLOBAL routines are actually intended to be called by
+the application, the performance cost of making them all DLL entry points is
+negligible.
+
+The unmodified IJG library presents a very C-specific application interface,
+so the resulting DLL is only usable from C or C++ applications.  There has
+been some talk of writing wrapper code that would present a simpler interface
+usable from other languages, such as Visual Basic.  This is on our to-do list
+but hasn't been very high priority --- any volunteers out there?
+
+
+Microsoft Windows, Borland C:
+
+The provided jconfig.bcc should work OK in a 32-bit Windows environment,
+but you'll need to tweak it in a 16-bit environment (you'd need to define
+NEED_FAR_POINTERS and MAX_ALLOC_CHUNK).  Beware that makefile.bcc will need
+alteration if you want to use it for Windows --- in particular, you should
+use jmemnobs.c not jmemdos.c under Windows.
+
+Borland C++ 4.5 fails with an internal compiler error when trying to compile
+jdmerge.c in 32-bit mode.  If enough people complain, perhaps Borland will fix
+it.  In the meantime, the simplest known workaround is to add a redundant
+definition of the variable range_limit in h2v1_merged_upsample(), at the head
+of the block that handles odd image width (about line 268 in v6 jdmerge.c):
+  /* If image width is odd, do the last output column separately */
+  if (cinfo->output_width & 1) {
+    register JSAMPLE * range_limit = cinfo->sample_range_limit; /* ADD THIS */
+    cb = GETJSAMPLE(*inptr1);
+Pretty bizarre, especially since the very similar routine h2v2_merged_upsample
+doesn't trigger the bug.
+Recent reports suggest that this bug does not occur with "bcc32a" (the
+Pentium-optimized version of the compiler).
+
+Another report from a user of Borland C 4.5 was that incorrect code (leading
+to a color shift in processed images) was produced if any of the following
+optimization switch combinations were used: 
+	-Ot -Og
+	-Ot -Op
+	-Ot -Om
+So try backing off on optimization if you see such a problem.  (Are there
+several different releases all numbered "4.5"??)
+
+
+Microsoft Windows, Microsoft Visual C++:
+
+jconfig.vc should work OK with any Microsoft compiler for a 32-bit memory
+model.  makefile.vc is intended for command-line use.  (If you are using
+the Developer Studio environment, you may prefer the DevStudio project
+files; see below.)
+
+Some users feel that it's easier to call the library from C++ code if you
+force VC++ to treat the library as C++ code, which you can do by renaming
+all the *.c files to *.cpp (and adjusting the makefile to match).  This
+avoids the need to put extern "C" { ... } around #include "jpeglib.h" in
+your C++ application.
+
+
+Microsoft Windows, Microsoft Developer Studio:
+
+We include makefiles that should work as project files in DevStudio 4.2 or
+later.  There is a library makefile that builds the IJG library as a static
+Win32 library, and an application makefile that builds the sample applications
+as Win32 console applications.  (Even if you only want the library, we
+recommend building the applications so that you can run the self-test.)
+
+To use:
+1. Copy jconfig.vc to jconfig.h, makelib.ds to jpeg.mak, and
+   makeapps.ds to apps.mak.  (Note that the renaming is critical!)
+2. Click on the .mak files to construct project workspaces.
+   (If you are using DevStudio more recent than 4.2, you'll probably
+   get a message saying that the makefiles are being updated.)
+3. Build the library project, then the applications project.
+4. Move the application .exe files from `app`\Release to an
+   appropriate location on your path.
+5. To perform the self-test, execute the command line
+	NMAKE /f makefile.vc  test
+
+
+OS/2, Borland C++:
+
+Watch out for optimization bugs in older Borland compilers; you may need
+to back off the optimization switch settings.  See the comments in
+makefile.bcc.
+
+
+SGI:
+
+On some SGI systems, you may need to set "AR2= ar -ts" in the Makefile.
+If you are using configure, you can do this by saying
+	./configure RANLIB='ar -ts'
+This change is not needed on all SGIs.  Use it only if the make fails at the
+stage of linking the completed programs.
+
+On the MIPS R4000 architecture (Indy, etc.), the compiler option "-mips2"
+reportedly speeds up the float DCT method substantially, enough to make it
+faster than the default int method (but still slower than the fast int
+method).  If you use -mips2, you may want to alter the default DCT method to
+be float.  To do this, put "#define JDCT_DEFAULT JDCT_FLOAT" in jconfig.h.
+
+
+VMS:
+
+On an Alpha/VMS system with MMS, be sure to use the "/Marco=Alpha=1"
+qualifier with MMS when building the JPEG package.
+
+VAX/VMS v5.5-1 may have problems with the test step of the build procedure
+reporting differences when it compares the original and test images.  If the
+error points to the last block of the files, it is most likely bogus and may
+be safely ignored.  It seems to be because the files are Stream_LF and
+Backup/Compare has difficulty with the (presumably) null padded files.
+This problem was not observed on VAX/VMS v6.1 or AXP/VMS v6.1.
diff --git a/Utilities/ITK/Utilities/itkjpeg/jaricom.c b/Utilities/ITK/Utilities/itkjpeg/jaricom.c
new file mode 100644
index 0000000000000000000000000000000000000000..fac051804883863d1d58d69368ec44713e4e80e7
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jaricom.c
@@ -0,0 +1,15 @@
+/*
+ * jaricom.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file holds place for arithmetic entropy codec tables.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+INT32 jaritab[1];  /* dummy table */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcapimin.c b/Utilities/ITK/Utilities/itkjpeg/jcapimin.c
new file mode 100644
index 0000000000000000000000000000000000000000..7bb6e7b410fba4d4eca4b26c13236ea39fad6f75
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcapimin.c
@@ -0,0 +1,280 @@
+/*
+ * jcapimin.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the compression half
+ * of the JPEG library.  These are the "minimum" API routines that may be
+ * needed in either the normal full-compression case or the transcoding-only
+ * case.
+ *
+ * Most of the routines intended to be called directly by an application
+ * are in this file or in jcapistd.c.  But also see jcparam.c for
+ * parameter-setup helper routines, jcomapi.c for routines shared by
+ * compression and decompression, and jctrans.c for the transcoding case.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Initialization of a JPEG compression object.
+ * The error manager must already be set up (in case memory manager fails).
+ */
+
+GLOBAL(void)
+jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
+{
+  int i;
+
+  /* Guard against version mismatches between library and caller. */
+  cinfo->mem = NULL;    /* so jpeg_destroy knows mem mgr not called */
+  if (version != JPEG_LIB_VERSION)
+    ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
+  if (structsize != SIZEOF(struct jpeg_compress_struct))
+    ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, 
+       (int) SIZEOF(struct jpeg_compress_struct), (int) structsize);
+
+  /* For debugging purposes, we zero the whole master structure.
+   * But the application has already set the err pointer, and may have set
+   * client_data, so we have to save and restore those fields.
+   * Note: if application hasn't set client_data, tools like Purify may
+   * complain here.
+   */
+  {
+    struct jpeg_error_mgr * err = cinfo->err;
+    void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+    MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct));
+    cinfo->err = err;
+    cinfo->client_data = client_data;
+  }
+  cinfo->is_decompressor = FALSE;
+
+  /* Initialize a memory manager instance for this object */
+  jinit_memory_mgr((j_common_ptr) cinfo);
+
+  /* Zero out pointers to permanent structures. */
+  cinfo->progress = NULL;
+  cinfo->dest = NULL;
+
+  cinfo->comp_info = NULL;
+
+  for (i = 0; i < NUM_QUANT_TBLS; i++)
+    cinfo->quant_tbl_ptrs[i] = NULL;
+
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    cinfo->dc_huff_tbl_ptrs[i] = NULL;
+    cinfo->ac_huff_tbl_ptrs[i] = NULL;
+  }
+
+  cinfo->script_space = NULL;
+
+  cinfo->input_gamma = 1.0;  /* in case application forgets */
+
+  /* OK, I'm ready */
+  cinfo->global_state = CSTATE_START;
+}
+
+
+/*
+ * Destruction of a JPEG compression object
+ */
+
+GLOBAL(void)
+jpeg_destroy_compress (j_compress_ptr cinfo)
+{
+  jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Abort processing of a JPEG compression operation,
+ * but don't destroy the object itself.
+ */
+
+GLOBAL(void)
+jpeg_abort_compress (j_compress_ptr cinfo)
+{
+  jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Forcibly suppress or un-suppress all quantization and Huffman tables.
+ * Marks all currently defined tables as already written (if suppress)
+ * or not written (if !suppress).  This will control whether they get emitted
+ * by a subsequent jpeg_start_compress call.
+ *
+ * This routine is exported for use by applications that want to produce
+ * abbreviated JPEG datastreams.  It logically belongs in jcparam.c, but
+ * since it is called by jpeg_start_compress, we put it here --- otherwise
+ * jcparam.o would be linked whether the application used it or not.
+ */
+
+GLOBAL(void)
+jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
+{
+  int i;
+  JQUANT_TBL * qtbl;
+  JHUFF_TBL * htbl;
+
+  for (i = 0; i < NUM_QUANT_TBLS; i++) {
+    if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)
+      qtbl->sent_table = suppress;
+  }
+
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)
+      htbl->sent_table = suppress;
+    if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL)
+      htbl->sent_table = suppress;
+  }
+}
+
+
+/*
+ * Finish JPEG compression.
+ *
+ * If a multipass operating mode was selected, this may do a great deal of
+ * work including most of the actual output.
+ */
+
+GLOBAL(void)
+jpeg_finish_compress (j_compress_ptr cinfo)
+{
+  JDIMENSION iMCU_row;
+
+  if (cinfo->global_state == CSTATE_SCANNING ||
+      cinfo->global_state == CSTATE_RAW_OK) {
+    /* Terminate first pass */
+    if (cinfo->next_scanline < cinfo->image_height)
+      ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
+    (*cinfo->master->finish_pass) (cinfo);
+  } else if (cinfo->global_state != CSTATE_WRCOEFS)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  /* Perform any remaining passes */
+  while (! cinfo->master->is_last_pass) {
+    (*cinfo->master->prepare_for_pass) (cinfo);
+    for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
+      if (cinfo->progress != NULL) {
+  cinfo->progress->pass_counter = (long) iMCU_row;
+  cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;
+  (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+      }
+      /* We bypass the main controller and invoke coef controller directly;
+       * all work is being done from the coefficient buffer.
+       */
+      if (! (*cinfo->codec->compress_data) (cinfo, (JSAMPIMAGE) NULL))
+  ERREXIT(cinfo, JERR_CANT_SUSPEND);
+    }
+    (*cinfo->master->finish_pass) (cinfo);
+  }
+  /* Write EOI, do final cleanup */
+  (*cinfo->marker->write_file_trailer) (cinfo);
+  (*cinfo->dest->term_destination) (cinfo);
+  /* We can use jpeg_abort to release memory and reset global_state */
+  jpeg_abort((j_common_ptr) cinfo);
+}
+
+
+/*
+ * Write a special marker.
+ * This is only recommended for writing COM or APPn markers.
+ * Must be called after jpeg_start_compress() and before
+ * first call to jpeg_write_scanlines() or jpeg_write_raw_data().
+ */
+
+GLOBAL(void)
+jpeg_write_marker (j_compress_ptr cinfo, int marker,
+       const JOCTET *dataptr, unsigned int datalen)
+{
+  JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val));
+
+  if (cinfo->next_scanline != 0 ||
+      (cinfo->global_state != CSTATE_SCANNING &&
+       cinfo->global_state != CSTATE_RAW_OK &&
+       cinfo->global_state != CSTATE_WRCOEFS))
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  (*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
+  write_marker_byte = cinfo->marker->write_marker_byte;  /* copy for speed */
+  while (datalen--) {
+    (*write_marker_byte) (cinfo, *dataptr);
+    dataptr++;
+  }
+}
+
+/* Same, but piecemeal. */
+
+GLOBAL(void)
+jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+{
+  if (cinfo->next_scanline != 0 ||
+      (cinfo->global_state != CSTATE_SCANNING &&
+       cinfo->global_state != CSTATE_RAW_OK &&
+       cinfo->global_state != CSTATE_WRCOEFS))
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  (*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
+}
+
+GLOBAL(void)
+jpeg_write_m_byte (j_compress_ptr cinfo, int val)
+{
+  (*cinfo->marker->write_marker_byte) (cinfo, val);
+}
+
+
+/*
+ * Alternate compression function: just write an abbreviated table file.
+ * Before calling this, all parameters and a data destination must be set up.
+ *
+ * To produce a pair of files containing abbreviated tables and abbreviated
+ * image data, one would proceed as follows:
+ *
+ *    initialize JPEG object
+ *    set JPEG parameters
+ *    set destination to table file
+ *    jpeg_write_tables(cinfo);
+ *    set destination to image file
+ *    jpeg_start_compress(cinfo, FALSE);
+ *    write data...
+ *    jpeg_finish_compress(cinfo);
+ *
+ * jpeg_write_tables has the side effect of marking all tables written
+ * (same as jpeg_suppress_tables(..., TRUE)).  Thus a subsequent start_compress
+ * will not re-emit the tables unless it is passed write_all_tables=TRUE.
+ */
+
+GLOBAL(void)
+jpeg_write_tables (j_compress_ptr cinfo)
+{
+  if (cinfo->global_state != CSTATE_START)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  /* (Re)initialize error mgr and destination modules */
+  (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+  (*cinfo->dest->init_destination) (cinfo);
+  /* Initialize the marker writer ... bit of a crock to do it here. */
+  jinit_marker_writer(cinfo);
+  /* Write them tables! */
+  (*cinfo->marker->write_tables_only) (cinfo);
+  /* And clean up. */
+  (*cinfo->dest->term_destination) (cinfo);
+  /*
+   * In library releases up through v6a, we called jpeg_abort() here to free
+   * any working memory allocated by the destination manager and marker
+   * writer.  Some applications had a problem with that: they allocated space
+   * of their own from the library memory manager, and didn't want it to go
+   * away during write_tables.  So now we do nothing.  This will cause a
+   * memory leak if an app calls write_tables repeatedly without doing a full
+   * compression cycle or otherwise resetting the JPEG object.  However, that
+   * seems less bad than unexpectedly freeing memory in the normal case.
+   * An app that prefers the old behavior can call jpeg_abort for itself after
+   * each call to jpeg_write_tables().
+   */
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcapistd.c b/Utilities/ITK/Utilities/itkjpeg/jcapistd.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee2a8496e09e24e29c02d7b192559d8894c680a9
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcapistd.c
@@ -0,0 +1,161 @@
+/*
+ * jcapistd.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the compression half
+ * of the JPEG library.  These are the "standard" API routines that are
+ * used in the normal full-compression case.  They are not used by a
+ * transcoding-only application.  Note that if an application links in
+ * jpeg_start_compress, it will end up linking in the entire compressor.
+ * We thus must separate this file from jcapimin.c to avoid linking the
+ * whole compression library into a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Compression initialization.
+ * Before calling this, all parameters and a data destination must be set up.
+ *
+ * We require a write_all_tables parameter as a failsafe check when writing
+ * multiple datastreams from the same compression object.  Since prior runs
+ * will have left all the tables marked sent_table=TRUE, a subsequent run
+ * would emit an abbreviated stream (no tables) by default.  This may be what
+ * is wanted, but for safety's sake it should not be the default behavior:
+ * programmers should have to make a deliberate choice to emit abbreviated
+ * images.  Therefore the documentation and examples should encourage people
+ * to pass write_all_tables=TRUE; then it will take active thought to do the
+ * wrong thing.
+ */
+
+GLOBAL(void)
+jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
+{
+  if (cinfo->global_state != CSTATE_START)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  if (write_all_tables)
+    jpeg_suppress_tables(cinfo, FALSE);  /* mark all tables to be written */
+
+  /* (Re)initialize error mgr and destination modules */
+  (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+  (*cinfo->dest->init_destination) (cinfo);
+  /* Perform master selection of active modules */
+  jinit_compress_master(cinfo);
+  /* Set up for the first pass */
+  (*cinfo->master->prepare_for_pass) (cinfo);
+  /* Ready for application to drive first pass through jpeg_write_scanlines
+   * or jpeg_write_raw_data.
+   */
+  cinfo->next_scanline = 0;
+  cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
+}
+
+
+/*
+ * Write some scanlines of data to the JPEG compressor.
+ *
+ * The return value will be the number of lines actually written.
+ * This should be less than the supplied num_lines only in case that
+ * the data destination module has requested suspension of the compressor,
+ * or if more than image_height scanlines are passed in.
+ *
+ * Note: we warn about excess calls to jpeg_write_scanlines() since
+ * this likely signals an application programmer error.  However,
+ * excess scanlines passed in the last valid call are *silently* ignored,
+ * so that the application need not adjust num_lines for end-of-image
+ * when using a multiple-scanline buffer.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
+          JDIMENSION num_lines)
+{
+  JDIMENSION row_ctr, rows_left;
+
+  if (cinfo->global_state != CSTATE_SCANNING)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  if (cinfo->next_scanline >= cinfo->image_height)
+    WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+
+  /* Call progress monitor hook if present */
+  if (cinfo->progress != NULL) {
+    cinfo->progress->pass_counter = (long) cinfo->next_scanline;
+    cinfo->progress->pass_limit = (long) cinfo->image_height;
+    (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+  }
+
+  /* Give master control module another chance if this is first call to
+   * jpeg_write_scanlines.  This lets output of the frame/scan headers be
+   * delayed so that application can write COM, etc, markers between
+   * jpeg_start_compress and jpeg_write_scanlines.
+   */
+  if (cinfo->master->call_pass_startup)
+    (*cinfo->master->pass_startup) (cinfo);
+
+  /* Ignore any extra scanlines at bottom of image. */
+  rows_left = cinfo->image_height - cinfo->next_scanline;
+  if (num_lines > rows_left)
+    num_lines = rows_left;
+
+  row_ctr = 0;
+  (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
+  cinfo->next_scanline += row_ctr;
+  return row_ctr;
+}
+
+
+/*
+ * Alternate entry point to write raw data.
+ * Processes exactly one iMCU row per call, unless suspended.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
+         JDIMENSION num_lines)
+{
+  JDIMENSION lines_per_iMCU_row;
+
+  if (cinfo->global_state != CSTATE_RAW_OK)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  if (cinfo->next_scanline >= cinfo->image_height) {
+    WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+    return 0;
+  }
+
+  /* Call progress monitor hook if present */
+  if (cinfo->progress != NULL) {
+    cinfo->progress->pass_counter = (long) cinfo->next_scanline;
+    cinfo->progress->pass_limit = (long) cinfo->image_height;
+    (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+  }
+
+  /* Give master control module another chance if this is first call to
+   * jpeg_write_raw_data.  This lets output of the frame/scan headers be
+   * delayed so that application can write COM, etc, markers between
+   * jpeg_start_compress and jpeg_write_raw_data.
+   */
+  if (cinfo->master->call_pass_startup)
+    (*cinfo->master->pass_startup) (cinfo);
+
+  /* Verify that at least one iMCU row has been passed. */
+  lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->data_unit;
+  if (num_lines < lines_per_iMCU_row)
+    ERREXIT(cinfo, JERR_BUFFER_SIZE);
+
+  /* Directly compress the row. */
+  if (! (*cinfo->codec->compress_data) (cinfo, data)) {
+    /* If compressor did not consume the whole row, suspend processing. */
+    return 0;
+  }
+
+  /* OK, we processed one iMCU row. */
+  cinfo->next_scanline += lines_per_iMCU_row;
+  return lines_per_iMCU_row;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcarith.c b/Utilities/ITK/Utilities/itkjpeg/jcarith.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a1793610eee94e2d73c8a5687a454c23693b403
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcarith.c
@@ -0,0 +1,24 @@
+/*
+ * jcarith.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file holds place for arithmetic entropy encoding routines.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Module initialization routine for arithmetic entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_arith_encoder (j_compress_ptr cinfo)
+{
+  ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jccoefct.c b/Utilities/ITK/Utilities/itkjpeg/jccoefct.c
new file mode 100644
index 0000000000000000000000000000000000000000..cad73c87bb9e3cdb2c0f40e780c0c48c49c8e77d
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jccoefct.c
@@ -0,0 +1,455 @@
+/*
+ * jccoefct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the coefficient buffer controller for compression.
+ * This controller is the top level of the JPEG compressor proper.
+ * The coefficient buffer lies between forward-DCT and entropy encoding steps.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"    /* Private declarations for lossy codec */
+
+
+/* We use a full-image coefficient buffer when doing Huffman optimization,
+ * and also for writing multiple-scan JPEG files.  In all cases, the DCT
+ * step is run during the first pass, and subsequent passes need only read
+ * the buffered coefficients.
+ */
+#ifdef ENTROPY_OPT_SUPPORTED
+#define FULL_COEF_BUFFER_SUPPORTED
+#else
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+#define FULL_COEF_BUFFER_SUPPORTED
+#endif
+#endif
+
+
+/* Private buffer controller object */
+
+typedef struct {
+  JDIMENSION iMCU_row_num;  /* iMCU row # within image */
+  JDIMENSION mcu_ctr;    /* counts MCUs processed in current row */
+  int MCU_vert_offset;    /* counts MCU rows within iMCU row */
+  int MCU_rows_per_iMCU_row;  /* number of such rows needed */
+
+  /* For single-pass compression, it's sufficient to buffer just one MCU
+   * (although this may prove a bit slow in practice).  We allocate a
+   * workspace of C_MAX_DATA_UNITS_IN_MCU coefficient blocks, and reuse it for
+   * each MCU constructed and sent.  (On 80x86, the workspace is FAR even
+   * though it's not really very big; this is to keep the module interfaces
+   * unchanged when a large coefficient buffer is necessary.)
+   * In multi-pass modes, this array points to the current MCU's blocks
+   * within the virtual arrays.
+   */
+  JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU];
+
+  /* In multi-pass modes, we need a virtual block array for each component. */
+  jvirt_barray_ptr whole_image[MAX_COMPONENTS];
+} c_coef_controller;
+
+typedef c_coef_controller * c_coef_ptr;
+
+
+/* Forward declarations */
+METHODDEF(boolean) compress_data
+    JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+METHODDEF(boolean) compress_first_pass
+    JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+METHODDEF(boolean) compress_output
+    JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_compress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row */
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+
+  /* In an interleaved scan, an MCU row is the same as an iMCU row.
+   * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+   * But at the bottom of the image, process only what's left.
+   */
+  if (cinfo->comps_in_scan > 1) {
+    coef->MCU_rows_per_iMCU_row = 1;
+  } else {
+    if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+    else
+      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+  }
+
+  coef->mcu_ctr = 0;
+  coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+
+  coef->iMCU_row_num = 0;
+  start_iMCU_row(cinfo);
+
+  switch (pass_mode) {
+  case JBUF_PASS_THRU:
+    if (coef->whole_image[0] != NULL)
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    lossyc->pub.compress_data = compress_data;
+    break;
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+  case JBUF_SAVE_AND_PASS:
+    if (coef->whole_image[0] == NULL)
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    lossyc->pub.compress_data = compress_first_pass;
+    break;
+  case JBUF_CRANK_DEST:
+    if (coef->whole_image[0] == NULL)
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    lossyc->pub.compress_data = compress_output;
+    break;
+#endif
+  default:
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    break;
+  }
+}
+
+
+/*
+ * Process some data in the single-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the image.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(boolean)
+compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+  JDIMENSION MCU_col_num;  /* index of current MCU within row */
+  JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+  int blkn, bi, ci, yindex, yoffset, blockcnt;
+  JDIMENSION ypos, xpos;
+  jpeg_component_info *compptr;
+
+  /* Loop to write as much as one whole iMCU row */
+  for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+       yoffset++) {
+    for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
+   MCU_col_num++) {
+      /* Determine where data comes from in input_buf and do the DCT thing.
+       * Each call on forward_DCT processes a horizontal row of DCT blocks
+       * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
+       * sequentially.  Dummy blocks at the right or bottom edge are filled in
+       * specially.  The data in them does not matter for image reconstruction,
+       * so we fill them with values that will encode to the smallest amount of
+       * data, viz: all zeroes in the AC entries, DC entries equal to previous
+       * block's DC value.  (Thanks to Thomas Kinsman for this idea.)
+       */
+      blkn = 0;
+      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+  compptr = cinfo->cur_comp_info[ci];
+  blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+            : compptr->last_col_width;
+  xpos = MCU_col_num * compptr->MCU_sample_width;
+  ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
+  for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+    if (coef->iMCU_row_num < last_iMCU_row ||
+        yoffset+yindex < compptr->last_row_height) {
+      (*lossyc->fdct_forward_DCT) (cinfo, compptr,
+            input_buf[compptr->component_index],
+            coef->MCU_buffer[blkn],
+            ypos, xpos, (JDIMENSION) blockcnt);
+      if (blockcnt < compptr->MCU_width) {
+        /* Create some dummy blocks at the right edge of the image. */
+        jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
+      (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
+        for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
+    coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
+        }
+      }
+    } else {
+      /* Create a row of dummy blocks at the bottom of the image. */
+      jzero_far((void FAR *) coef->MCU_buffer[blkn],
+          compptr->MCU_width * SIZEOF(JBLOCK));
+      for (bi = 0; bi < compptr->MCU_width; bi++) {
+        coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
+      }
+    }
+    blkn += compptr->MCU_width;
+    ypos += DCTSIZE;
+  }
+      }
+      /* Try to write the MCU.  In event of a suspension failure, we will
+       * re-DCT the MCU on restart (a bit inefficient, could be fixed...)
+       */
+      if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) {
+  /* Suspension forced; update state counters and exit */
+  coef->MCU_vert_offset = yoffset;
+  coef->mcu_ctr = MCU_col_num;
+  return FALSE;
+      }
+    }
+    /* Completed an MCU row, but perhaps not an iMCU row */
+    coef->mcu_ctr = 0;
+  }
+  /* Completed the iMCU row, advance counters for next one */
+  coef->iMCU_row_num++;
+  start_iMCU_row(cinfo);
+  return TRUE;
+}
+
+
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+
+/*
+ * Process some data in the first pass of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the image.
+ * This amount of data is read from the source buffer, DCT'd and quantized,
+ * and saved into the virtual arrays.  We also generate suitable dummy blocks
+ * as needed at the right and lower edges.  (The dummy blocks are constructed
+ * in the virtual arrays, which have been padded appropriately.)  This makes
+ * it possible for subsequent passes not to worry about real vs. dummy blocks.
+ *
+ * We must also emit the data to the entropy encoder.  This is conveniently
+ * done by calling compress_output() after we've loaded the current strip
+ * of the virtual arrays.
+ *
+ * NB: input_buf contains a plane for each component in image.  All
+ * components are DCT'd and loaded into the virtual arrays in this pass.
+ * However, it may be that only a subset of the components are emitted to
+ * the entropy encoder during this first pass; be careful about looking
+ * at the scan-dependent variables (MCU dimensions, etc).
+ */
+
+METHODDEF(boolean)
+compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+  JDIMENSION blocks_across, MCUs_across, MCUindex;
+  int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
+  JCOEF lastDC;
+  jpeg_component_info *compptr;
+  JBLOCKARRAY buffer;
+  JBLOCKROW thisblockrow, lastblockrow;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Align the virtual buffer for this component. */
+    buffer = (*cinfo->mem->access_virt_barray)
+      ((j_common_ptr) cinfo, coef->whole_image[ci],
+       coef->iMCU_row_num * compptr->v_samp_factor,
+       (JDIMENSION) compptr->v_samp_factor, TRUE);
+    /* Count non-dummy DCT block rows in this iMCU row. */
+    if (coef->iMCU_row_num < last_iMCU_row)
+      block_rows = compptr->v_samp_factor;
+    else {
+      /* NB: can't use last_row_height here, since may not be set! */
+      block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+      if (block_rows == 0) block_rows = compptr->v_samp_factor;
+    }
+    blocks_across = compptr->width_in_data_units;
+    h_samp_factor = compptr->h_samp_factor;
+    /* Count number of dummy blocks to be added at the right margin. */
+    ndummy = (int) (blocks_across % h_samp_factor);
+    if (ndummy > 0)
+      ndummy = h_samp_factor - ndummy;
+    /* Perform DCT for all non-dummy blocks in this iMCU row.  Each call
+     * on forward_DCT processes a complete horizontal row of DCT blocks.
+     */
+    for (block_row = 0; block_row < block_rows; block_row++) {
+      thisblockrow = buffer[block_row];
+      (*lossyc->fdct_forward_DCT) (cinfo, compptr,
+           input_buf[ci], thisblockrow,
+           (JDIMENSION) (block_row * DCTSIZE),
+           (JDIMENSION) 0, blocks_across);
+      if (ndummy > 0) {
+  /* Create dummy blocks at the right edge of the image. */
+  thisblockrow += blocks_across; /* => first dummy block */
+  jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
+  lastDC = thisblockrow[-1][0];
+  for (bi = 0; bi < ndummy; bi++) {
+    thisblockrow[bi][0] = lastDC;
+  }
+      }
+    }
+    /* If at end of image, create dummy block rows as needed.
+     * The tricky part here is that within each MCU, we want the DC values
+     * of the dummy blocks to match the last real block's DC value.
+     * This squeezes a few more bytes out of the resulting file...
+     */
+    if (coef->iMCU_row_num == last_iMCU_row) {
+      blocks_across += ndummy;  /* include lower right corner */
+      MCUs_across = blocks_across / h_samp_factor;
+      for (block_row = block_rows; block_row < compptr->v_samp_factor;
+     block_row++) {
+  thisblockrow = buffer[block_row];
+  lastblockrow = buffer[block_row-1];
+  jzero_far((void FAR *) thisblockrow,
+      (size_t) (blocks_across * SIZEOF(JBLOCK)));
+  for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
+    lastDC = lastblockrow[h_samp_factor-1][0];
+    for (bi = 0; bi < h_samp_factor; bi++) {
+      thisblockrow[bi][0] = lastDC;
+    }
+    thisblockrow += h_samp_factor; /* advance to next MCU in row */
+    lastblockrow += h_samp_factor;
+  }
+      }
+    }
+  }
+  /* NB: compress_output will increment iMCU_row_num if successful.
+   * A suspension return will result in redoing all the work above next time.
+   */
+
+  /* Emit data to the entropy encoder, sharing code with subsequent passes */
+  return compress_output(cinfo, input_buf);
+}
+
+
+/*
+ * Process some data in subsequent passes of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the scan.
+ * The data is obtained from the virtual arrays and fed to the entropy coder.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf is ignored; it is likely to be a NULL pointer.
+ */
+
+METHODDEF(boolean)
+compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+  JDIMENSION MCU_col_num;  /* index of current MCU within row */
+  int blkn, ci, xindex, yindex, yoffset;
+  JDIMENSION start_col;
+  JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+  JBLOCKROW buffer_ptr;
+  jpeg_component_info *compptr;
+  (void)input_buf;
+
+  /* Align the virtual buffers for the components used in this scan.
+   * NB: during first pass, this is safe only because the buffers will
+   * already be aligned properly, so jmemmgr.c won't need to do any I/O.
+   */
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    buffer[ci] = (*cinfo->mem->access_virt_barray)
+      ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+       coef->iMCU_row_num * compptr->v_samp_factor,
+       (JDIMENSION) compptr->v_samp_factor, FALSE);
+  }
+
+  /* Loop to process one whole iMCU row */
+  for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+       yoffset++) {
+    for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
+   MCU_col_num++) {
+      /* Construct list of pointers to DCT blocks belonging to this MCU */
+      blkn = 0;      /* index of current DCT block within MCU */
+      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+  compptr = cinfo->cur_comp_info[ci];
+  start_col = MCU_col_num * compptr->MCU_width;
+  for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+    buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+    for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
+      coef->MCU_buffer[blkn++] = buffer_ptr++;
+    }
+  }
+      }
+      /* Try to write the MCU. */
+      if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) {
+  /* Suspension forced; update state counters and exit */
+  coef->MCU_vert_offset = yoffset;
+  coef->mcu_ctr = MCU_col_num;
+  return FALSE;
+      }
+    }
+    /* Completed an MCU row, but perhaps not an iMCU row */
+    coef->mcu_ctr = 0;
+  }
+  /* Completed the iMCU row, advance counters for next one */
+  coef->iMCU_row_num++;
+  start_iMCU_row(cinfo);
+  return TRUE;
+}
+
+#endif /* FULL_COEF_BUFFER_SUPPORTED */
+
+
+/*
+ * Initialize coefficient buffer controller.
+ */
+
+GLOBAL(void)
+jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  c_coef_ptr coef;
+
+  coef = (c_coef_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(c_coef_controller));
+  lossyc->coef_private = (struct jpeg_c_coef_controller *) coef;
+  lossyc->coef_start_pass = start_pass_coef;
+
+  /* Create the coefficient buffer. */
+  if (need_full_buffer) {
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+    /* Allocate a full-image virtual array for each component, */
+    /* padded to a multiple of samp_factor DCT blocks in each direction. */
+    int ci;
+    jpeg_component_info *compptr;
+
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
+  ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+   (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+        (long) compptr->h_samp_factor),
+   (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+        (long) compptr->v_samp_factor),
+   (JDIMENSION) compptr->v_samp_factor);
+    }
+#else
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+  } else {
+    /* We only need a single-MCU buffer. */
+    JBLOCKROW buffer;
+    int i;
+
+    buffer = (JBLOCKROW)
+      (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
+    for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) {
+      coef->MCU_buffer[i] = buffer + i;
+    }
+    coef->whole_image[0] = NULL; /* flag for no virtual arrays */
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jccolor.c b/Utilities/ITK/Utilities/itkjpeg/jccolor.c
new file mode 100644
index 0000000000000000000000000000000000000000..a0afd61bb3de1b57c7dc004da8e5dd25879a7ba9
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jccolor.c
@@ -0,0 +1,460 @@
+/*
+ * jccolor.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains input colorspace conversion routines.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private subobject */
+
+typedef struct {
+  struct jpeg_color_converter pub; /* public fields */
+
+  /* Private state for RGB->YCC conversion */
+  INT32 * rgb_ycc_tab;    /* => table for RGB to YCbCr conversion */
+} my_color_converter;
+
+typedef my_color_converter * my_cconvert_ptr;
+
+
+/**************** RGB -> YCbCr conversion: most common case **************/
+
+/*
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ *  Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
+ *  Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B  + CENTERJSAMPLE
+ *  Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B  + CENTERJSAMPLE
+ * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
+ * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
+ * rather than CENTERJSAMPLE, for Cb and Cr.  This gave equal positive and
+ * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
+ * were not represented exactly.  Now we sacrifice exact representation of
+ * maximum red and maximum blue in order to get exact grayscales.
+ *
+ * To avoid floating-point arithmetic, we represent the fractional constants
+ * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
+ * the products by 2^16, with appropriate rounding, to get the correct answer.
+ *
+ * For even more speed, we avoid doing any multiplications in the inner loop
+ * by precalculating the constants times R,G,B for all possible values.
+ * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
+ * for 12-bit samples it is still acceptable.  It's not very reasonable for
+ * 16-bit samples, but if you want lossless storage you shouldn't be changing
+ * colorspace anyway.
+ * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
+ * in the tables to save adding them separately in the inner loop.
+ */
+
+#define SCALEBITS  16  /* speediest right-shift on some machines */
+#define CBCR_OFFSET  ((INT32) CENTERJSAMPLE << SCALEBITS)
+#define ONE_HALF  ((INT32) 1 << (SCALEBITS-1))
+#define FIX(x)    ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+/* We allocate one big table and divide it up into eight parts, instead of
+ * doing eight alloc_small requests.  This lets us use a single table base
+ * address, which can be held in a register in the inner loops on many
+ * machines (more than can hold all eight addresses, anyway).
+ */
+
+#define R_Y_OFF    0      /* offset to R => Y section */
+#define G_Y_OFF    (1*(MAXJSAMPLE+1))  /* offset to G => Y section */
+#define B_Y_OFF    (2*(MAXJSAMPLE+1))  /* etc. */
+#define R_CB_OFF  (3*(MAXJSAMPLE+1))
+#define G_CB_OFF  (4*(MAXJSAMPLE+1))
+#define B_CB_OFF  (5*(MAXJSAMPLE+1))
+#define R_CR_OFF  B_CB_OFF    /* B=>Cb, R=>Cr are the same */
+#define G_CR_OFF  (6*(MAXJSAMPLE+1))
+#define B_CR_OFF  (7*(MAXJSAMPLE+1))
+#define TABLE_SIZE  (8*(MAXJSAMPLE+1))
+
+
+/*
+ * Initialize for RGB->YCC colorspace conversion.
+ */
+
+METHODDEF(void)
+rgb_ycc_start (j_compress_ptr cinfo)
+{
+  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+  INT32 * rgb_ycc_tab;
+  INT32 i;
+
+  /* Allocate and fill in the conversion tables. */
+  cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        (TABLE_SIZE * SIZEOF(INT32)));
+
+  for (i = 0; i <= MAXJSAMPLE; i++) {
+    rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
+    rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
+    rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i     + ONE_HALF;
+    rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
+    rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
+    /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
+     * This ensures that the maximum output will round to MAXJSAMPLE
+     * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
+     */
+    rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1;
+/*  B=>Cb and R=>Cr tables are the same
+    rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1;
+*/
+    rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
+    rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
+  }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ *
+ * Note that we change from the application's interleaved-pixel format
+ * to our internal noninterleaved, one-plane-per-component format.
+ * The input buffer is therefore three times as wide as the output buffer.
+ *
+ * A starting row offset is provided only for the output buffer.  The caller
+ * can easily adjust the passed input_buf value to accommodate any row
+ * offset required on that side.
+ */
+
+METHODDEF(void)
+rgb_ycc_convert (j_compress_ptr cinfo,
+     JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+     JDIMENSION output_row, int num_rows)
+{
+  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+  register int r, g, b;
+  register INT32 * ctab = cconvert->rgb_ycc_tab;
+  register JSAMPROW inptr;
+  register JSAMPROW outptr0, outptr1, outptr2;
+  register JDIMENSION col;
+  JDIMENSION num_cols = cinfo->image_width;
+
+  while (--num_rows >= 0) {
+    inptr = *input_buf++;
+    outptr0 = output_buf[0][output_row];
+    outptr1 = output_buf[1][output_row];
+    outptr2 = output_buf[2][output_row];
+    output_row++;
+    for (col = 0; col < num_cols; col++) {
+      r = GETJSAMPLE(inptr[RGB_RED]);
+      g = GETJSAMPLE(inptr[RGB_GREEN]);
+      b = GETJSAMPLE(inptr[RGB_BLUE]);
+      inptr += RGB_PIXELSIZE;
+      /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
+       * must be too; we do not need an explicit range-limiting operation.
+       * Hence the value being shifted is never negative, and we don't
+       * need the general RIGHT_SHIFT macro.
+       */
+      /* Y */
+      outptr0[col] = (JSAMPLE)
+    ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+     >> SCALEBITS);
+      /* Cb */
+      outptr1[col] = (JSAMPLE)
+    ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
+     >> SCALEBITS);
+      /* Cr */
+      outptr2[col] = (JSAMPLE)
+    ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
+     >> SCALEBITS);
+    }
+  }
+}
+
+
+/**************** Cases other than RGB -> YCbCr **************/
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles RGB->grayscale conversion, which is the same
+ * as the RGB->Y portion of RGB->YCbCr.
+ * We assume rgb_ycc_start has been called (we only use the Y tables).
+ */
+
+METHODDEF(void)
+rgb_gray_convert (j_compress_ptr cinfo,
+      JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+      JDIMENSION output_row, int num_rows)
+{
+  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+  register int r, g, b;
+  register INT32 * ctab = cconvert->rgb_ycc_tab;
+  register JSAMPROW inptr;
+  register JSAMPROW outptr;
+  register JDIMENSION col;
+  JDIMENSION num_cols = cinfo->image_width;
+
+  while (--num_rows >= 0) {
+    inptr = *input_buf++;
+    outptr = output_buf[0][output_row];
+    output_row++;
+    for (col = 0; col < num_cols; col++) {
+      r = GETJSAMPLE(inptr[RGB_RED]);
+      g = GETJSAMPLE(inptr[RGB_GREEN]);
+      b = GETJSAMPLE(inptr[RGB_BLUE]);
+      inptr += RGB_PIXELSIZE;
+      /* Y */
+      outptr[col] = (JSAMPLE)
+    ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+     >> SCALEBITS);
+    }
+  }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles Adobe-style CMYK->YCCK conversion,
+ * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
+ * conversion as above, while passing K (black) unchanged.
+ * We assume rgb_ycc_start has been called.
+ */
+
+METHODDEF(void)
+cmyk_ycck_convert (j_compress_ptr cinfo,
+       JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+       JDIMENSION output_row, int num_rows)
+{
+  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+  register int r, g, b;
+  register INT32 * ctab = cconvert->rgb_ycc_tab;
+  register JSAMPROW inptr;
+  register JSAMPROW outptr0, outptr1, outptr2, outptr3;
+  register JDIMENSION col;
+  JDIMENSION num_cols = cinfo->image_width;
+
+  while (--num_rows >= 0) {
+    inptr = *input_buf++;
+    outptr0 = output_buf[0][output_row];
+    outptr1 = output_buf[1][output_row];
+    outptr2 = output_buf[2][output_row];
+    outptr3 = output_buf[3][output_row];
+    output_row++;
+    for (col = 0; col < num_cols; col++) {
+      r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
+      g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
+      b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
+      /* K passes through as-is */
+      outptr3[col] = inptr[3];  /* don't need GETJSAMPLE here */
+      inptr += 4;
+      /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
+       * must be too; we do not need an explicit range-limiting operation.
+       * Hence the value being shifted is never negative, and we don't
+       * need the general RIGHT_SHIFT macro.
+       */
+      /* Y */
+      outptr0[col] = (JSAMPLE)
+    ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+     >> SCALEBITS);
+      /* Cb */
+      outptr1[col] = (JSAMPLE)
+    ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
+     >> SCALEBITS);
+      /* Cr */
+      outptr2[col] = (JSAMPLE)
+    ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
+     >> SCALEBITS);
+    }
+  }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles grayscale output with no conversion.
+ * The source can be either plain grayscale or YCbCr (since Y == gray).
+ */
+
+METHODDEF(void)
+grayscale_convert (j_compress_ptr cinfo,
+       JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+       JDIMENSION output_row, int num_rows)
+{
+  register JSAMPROW inptr;
+  register JSAMPROW outptr;
+  register JDIMENSION col;
+  JDIMENSION num_cols = cinfo->image_width;
+  int instride = cinfo->input_components;
+
+  while (--num_rows >= 0) {
+    inptr = *input_buf++;
+    outptr = output_buf[0][output_row];
+    output_row++;
+    for (col = 0; col < num_cols; col++) {
+      outptr[col] = inptr[0];  /* don't need GETJSAMPLE() here */
+      inptr += instride;
+    }
+  }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles multi-component colorspaces without conversion.
+ * We assume input_components == num_components.
+ */
+
+METHODDEF(void)
+null_convert (j_compress_ptr cinfo,
+        JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+        JDIMENSION output_row, int num_rows)
+{
+  register JSAMPROW inptr;
+  register JSAMPROW outptr;
+  register JDIMENSION col;
+  register int ci;
+  int nc = cinfo->num_components;
+  JDIMENSION num_cols = cinfo->image_width;
+
+  while (--num_rows >= 0) {
+    /* It seems fastest to make a separate pass for each component. */
+    for (ci = 0; ci < nc; ci++) {
+      inptr = *input_buf;
+      outptr = output_buf[ci][output_row];
+      for (col = 0; col < num_cols; col++) {
+  outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
+  inptr += nc;
+      }
+    }
+    input_buf++;
+    output_row++;
+  }
+}
+
+
+/*
+ * Empty method for start_pass.
+ */
+
+METHODDEF(void)
+null_method (j_compress_ptr cinfo)
+{
+  (void)cinfo;
+  /* no work needed */
+}
+
+
+/*
+ * Module initialization routine for input colorspace conversion.
+ */
+
+GLOBAL(void)
+jinit_color_converter (j_compress_ptr cinfo)
+{
+  my_cconvert_ptr cconvert;
+
+  cconvert = (my_cconvert_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_color_converter));
+  cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
+  /* set start_pass to null method until we find out differently */
+  cconvert->pub.start_pass = null_method;
+
+  /* Make sure input_components agrees with in_color_space */
+  switch (cinfo->in_color_space) {
+  case JCS_GRAYSCALE:
+    if (cinfo->input_components != 1)
+      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+    break;
+
+  case JCS_RGB:
+#if RGB_PIXELSIZE != 3
+    if (cinfo->input_components != RGB_PIXELSIZE)
+      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+    break;
+#endif /* else share code with YCbCr */
+
+  case JCS_YCbCr:
+    if (cinfo->input_components != 3)
+      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+    break;
+
+  case JCS_CMYK:
+  case JCS_YCCK:
+    if (cinfo->input_components != 4)
+      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+    break;
+
+  default:      /* JCS_UNKNOWN can be anything */
+    if (cinfo->input_components < 1)
+      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+    break;
+  }
+
+  /* Check num_components, set conversion method based on requested space */
+  switch (cinfo->jpeg_color_space) {
+  case JCS_GRAYSCALE:
+    if (cinfo->num_components != 1)
+      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+    if (cinfo->in_color_space == JCS_GRAYSCALE)
+      cconvert->pub.color_convert = grayscale_convert;
+    else if (cinfo->in_color_space == JCS_RGB) {
+      cconvert->pub.start_pass = rgb_ycc_start;
+      cconvert->pub.color_convert = rgb_gray_convert;
+    } else if (cinfo->in_color_space == JCS_YCbCr)
+      cconvert->pub.color_convert = grayscale_convert;
+    else
+      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+    break;
+
+  case JCS_RGB:
+    if (cinfo->num_components != 3)
+      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+    if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
+      cconvert->pub.color_convert = null_convert;
+    else
+      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+    break;
+
+  case JCS_YCbCr:
+    if (cinfo->num_components != 3)
+      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+    if (cinfo->in_color_space == JCS_RGB) {
+      cconvert->pub.start_pass = rgb_ycc_start;
+      cconvert->pub.color_convert = rgb_ycc_convert;
+    } else if (cinfo->in_color_space == JCS_YCbCr)
+      cconvert->pub.color_convert = null_convert;
+    else
+      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+    break;
+
+  case JCS_CMYK:
+    if (cinfo->num_components != 4)
+      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+    if (cinfo->in_color_space == JCS_CMYK)
+      cconvert->pub.color_convert = null_convert;
+    else
+      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+    break;
+
+  case JCS_YCCK:
+    if (cinfo->num_components != 4)
+      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+    if (cinfo->in_color_space == JCS_CMYK) {
+      cconvert->pub.start_pass = rgb_ycc_start;
+      cconvert->pub.color_convert = cmyk_ycck_convert;
+    } else if (cinfo->in_color_space == JCS_YCCK)
+      cconvert->pub.color_convert = null_convert;
+    else
+      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+    break;
+
+  default:      /* allow null conversion of JCS_UNKNOWN */
+    if (cinfo->jpeg_color_space != cinfo->in_color_space ||
+  cinfo->num_components != cinfo->input_components)
+      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+    cconvert->pub.color_convert = null_convert;
+    break;
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcdctmgr.c b/Utilities/ITK/Utilities/itkjpeg/jcdctmgr.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b21799010cd40bcd41db0ff25fbeb531439811e
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcdctmgr.c
@@ -0,0 +1,390 @@
+/*
+ * jcdctmgr.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the forward-DCT management logic.
+ * This code selects a particular DCT implementation to be used,
+ * and it performs related housekeeping chores including coefficient
+ * quantization.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"    /* Private declarations for lossy codec */
+#include "jdct.h"    /* Private declarations for DCT subsystem */
+
+
+/* Private subobject for this module */
+
+typedef struct {
+  /* Pointer to the DCT routine actually in use */
+  forward_DCT_method_ptr do_dct;
+
+  /* The actual post-DCT divisors --- not identical to the quant table
+   * entries, because of scaling (especially for an unnormalized DCT).
+   * Each table is given in normal array order.
+   */
+  DCTELEM * divisors[NUM_QUANT_TBLS];
+
+#ifdef DCT_FLOAT_SUPPORTED
+  /* Same as above for the floating-point case. */
+  float_DCT_method_ptr do_float_dct;
+  FAST_FLOAT * float_divisors[NUM_QUANT_TBLS];
+#endif
+} fdct_controller;
+
+typedef fdct_controller * fdct_ptr;
+
+
+/*
+ * Initialize for a processing pass.
+ * Verify that all referenced Q-tables are present, and set up
+ * the divisor table for each one.
+ * In the current implementation, DCT of all components is done during
+ * the first pass, even if only some components will be output in the
+ * first scan.  Hence all components should be examined here.
+ */
+
+METHODDEF(void)
+start_pass_fdctmgr (j_compress_ptr cinfo)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private;
+  int ci, qtblno, i;
+  jpeg_component_info *compptr;
+  JQUANT_TBL * qtbl;
+  DCTELEM * dtbl;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    qtblno = compptr->quant_tbl_no;
+    /* Make sure specified quantization table is present */
+    if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
+  cinfo->quant_tbl_ptrs[qtblno] == NULL)
+      ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
+    qtbl = cinfo->quant_tbl_ptrs[qtblno];
+    /* Compute divisors for this quant table */
+    /* We may do this more than once for same table, but it's not a big deal */
+    switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+    case JDCT_ISLOW:
+      /* For LL&M IDCT method, divisors are equal to raw quantization
+       * coefficients multiplied by 8 (to counteract scaling).
+       */
+      if (fdct->divisors[qtblno] == NULL) {
+  fdct->divisors[qtblno] = (DCTELEM *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+              DCTSIZE2 * SIZEOF(DCTELEM));
+      }
+      dtbl = fdct->divisors[qtblno];
+      for (i = 0; i < DCTSIZE2; i++) {
+  dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
+      }
+      break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+    case JDCT_IFAST:
+      {
+  /* For AA&N IDCT method, divisors are equal to quantization
+   * coefficients scaled by scalefactor[row]*scalefactor[col], where
+   *   scalefactor[0] = 1
+   *   scalefactor[k] = cos(k*PI/16) * sqrt(2)    for k=1..7
+   * We apply a further scale factor of 8.
+   */
+#define CONST_BITS 14
+  static const INT16 aanscales[DCTSIZE2] = {
+    /* precomputed values scaled up by 14 bits */
+    16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
+    22725, 31521, 29692, 26722, 22725, 17855, 12299,  6270,
+    21407, 29692, 27969, 25172, 21407, 16819, 11585,  5906,
+    19266, 26722, 25172, 22654, 19266, 15137, 10426,  5315,
+    16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
+    12873, 17855, 16819, 15137, 12873, 10114,  6967,  3552,
+     8867, 12299, 11585, 10426,  8867,  6967,  4799,  2446,
+     4520,  6270,  5906,  5315,  4520,  3552,  2446,  1247
+  };
+  SHIFT_TEMPS
+
+  if (fdct->divisors[qtblno] == NULL) {
+    fdct->divisors[qtblno] = (DCTELEM *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          DCTSIZE2 * SIZEOF(DCTELEM));
+  }
+  dtbl = fdct->divisors[qtblno];
+  for (i = 0; i < DCTSIZE2; i++) {
+    dtbl[i] = (DCTELEM)
+      DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
+          (INT32) aanscales[i]),
+        CONST_BITS-3);
+  }
+      }
+      break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+    case JDCT_FLOAT:
+      {
+  /* For float AA&N IDCT method, divisors are equal to quantization
+   * coefficients scaled by scalefactor[row]*scalefactor[col], where
+   *   scalefactor[0] = 1
+   *   scalefactor[k] = cos(k*PI/16) * sqrt(2)    for k=1..7
+   * We apply a further scale factor of 8.
+   * What's actually stored is 1/divisor so that the inner loop can
+   * use a multiplication rather than a division.
+   */
+  FAST_FLOAT * fdtbl;
+  int row, col;
+  static const double aanscalefactor[DCTSIZE] = {
+    1.0, 1.387039845, 1.306562965, 1.175875602,
+    1.0, 0.785694958, 0.541196100, 0.275899379
+  };
+
+  if (fdct->float_divisors[qtblno] == NULL) {
+    fdct->float_divisors[qtblno] = (FAST_FLOAT *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          DCTSIZE2 * SIZEOF(FAST_FLOAT));
+  }
+  fdtbl = fdct->float_divisors[qtblno];
+  i = 0;
+  for (row = 0; row < DCTSIZE; row++) {
+    for (col = 0; col < DCTSIZE; col++) {
+      fdtbl[i] = (FAST_FLOAT)
+        (1.0 / (((double) qtbl->quantval[i] *
+           aanscalefactor[row] * aanscalefactor[col] * 8.0)));
+      i++;
+    }
+  }
+      }
+      break;
+#endif
+    default:
+      ERREXIT(cinfo, JERR_NOT_COMPILED);
+      break;
+    }
+  }
+}
+
+
+/*
+ * Perform forward DCT on one or more blocks of a component.
+ *
+ * The input samples are taken from the sample_data[] array starting at
+ * position start_row/start_col, and moving to the right for any additional
+ * blocks. The quantized coefficients are returned in coef_blocks[].
+ */
+
+METHODDEF(void)
+forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
+       JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+       JDIMENSION start_row, JDIMENSION start_col,
+       JDIMENSION num_blocks)
+/* This version is used for integer DCT implementations. */
+{
+  /* This routine is heavily used, so it's worth coding it tightly. */
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private;
+  forward_DCT_method_ptr do_dct = fdct->do_dct;
+  DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
+  DCTELEM workspace[DCTSIZE2];  /* work area for FDCT subroutine */
+  JDIMENSION bi;
+
+  sample_data += start_row;  /* fold in the vertical offset once */
+
+  for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
+    /* Load data into workspace, applying unsigned->signed conversion */
+    { register DCTELEM *workspaceptr;
+      register JSAMPROW elemptr;
+      register int elemr;
+
+      workspaceptr = workspace;
+      for (elemr = 0; elemr < DCTSIZE; elemr++) {
+  elemptr = sample_data[elemr] + start_col;
+#if DCTSIZE == 8    /* unroll the inner loop */
+  *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+  *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+  *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+  *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+  *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+  *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+  *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+  *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+#else
+  { register int elemc;
+    for (elemc = DCTSIZE; elemc > 0; elemc--) {
+      *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+    }
+  }
+#endif
+      }
+    }
+
+    /* Perform the DCT */
+    (*do_dct) (workspace);
+
+    /* Quantize/descale the coefficients, and store into coef_blocks[] */
+    { register DCTELEM temp, qval;
+      register int i;
+      register JCOEFPTR output_ptr = coef_blocks[bi];
+
+      for (i = 0; i < DCTSIZE2; i++) {
+  qval = divisors[i];
+  temp = workspace[i];
+  /* Divide the coefficient value by qval, ensuring proper rounding.
+   * Since C does not specify the direction of rounding for negative
+   * quotients, we have to force the dividend positive for portability.
+   *
+   * In most files, at least half of the output values will be zero
+   * (at default quantization settings, more like three-quarters...)
+   * so we should ensure that this case is fast.  On many machines,
+   * a comparison is enough cheaper than a divide to make a special test
+   * a win.  Since both inputs will be nonnegative, we need only test
+   * for a < b to discover whether a/b is 0.
+   * If your machine's division is fast enough, define FAST_DIVIDE.
+   */
+#ifdef FAST_DIVIDE
+#define DIVIDE_BY(a,b)  a /= b
+#else
+#define DIVIDE_BY(a,b)  if (a >= b) a /= b; else a = 0
+#endif
+  if (temp < 0) {
+    temp = -temp;
+    temp += qval>>1;  /* for rounding */
+    DIVIDE_BY(temp, qval);
+    temp = -temp;
+  } else {
+    temp += qval>>1;  /* for rounding */
+    DIVIDE_BY(temp, qval);
+  }
+  output_ptr[i] = (JCOEF) temp;
+      }
+    }
+  }
+}
+
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+METHODDEF(void)
+forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
+       JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+       JDIMENSION start_row, JDIMENSION start_col,
+       JDIMENSION num_blocks)
+/* This version is used for floating-point DCT implementations. */
+{
+  /* This routine is heavily used, so it's worth coding it tightly. */
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private;
+  float_DCT_method_ptr do_dct = fdct->do_float_dct;
+  FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
+  FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */
+  JDIMENSION bi;
+
+  sample_data += start_row;  /* fold in the vertical offset once */
+
+  for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
+    /* Load data into workspace, applying unsigned->signed conversion */
+    { register FAST_FLOAT *workspaceptr;
+      register JSAMPROW elemptr;
+      register int elemr;
+
+      workspaceptr = workspace;
+      for (elemr = 0; elemr < DCTSIZE; elemr++) {
+  elemptr = sample_data[elemr] + start_col;
+#if DCTSIZE == 8    /* unroll the inner loop */
+  *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+  *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+  *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+  *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+  *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+  *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+  *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+  *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+#else
+  { register int elemc;
+    for (elemc = DCTSIZE; elemc > 0; elemc--) {
+      *workspaceptr++ = (FAST_FLOAT)
+        (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+    }
+  }
+#endif
+      }
+    }
+
+    /* Perform the DCT */
+    (*do_dct) (workspace);
+
+    /* Quantize/descale the coefficients, and store into coef_blocks[] */
+    { register FAST_FLOAT temp;
+      register int i;
+      register JCOEFPTR output_ptr = coef_blocks[bi];
+
+      for (i = 0; i < DCTSIZE2; i++) {
+  /* Apply the quantization and scaling factor */
+  temp = workspace[i] * divisors[i];
+  /* Round to nearest integer.
+   * Since C does not specify the direction of rounding for negative
+   * quotients, we have to force the dividend positive for portability.
+   * The maximum coefficient size is +-16K (for 12-bit data), so this
+   * code should work for either 16-bit or 32-bit ints.
+   */
+  output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384);
+      }
+    }
+  }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
+
+
+/*
+ * Initialize FDCT manager.
+ */
+
+GLOBAL(void)
+jinit_forward_dct (j_compress_ptr cinfo)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  fdct_ptr fdct;
+  int i;
+
+  fdct = (fdct_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(fdct_controller));
+  lossyc->fdct_private = (struct jpeg_forward_dct *) fdct;
+  lossyc->fdct_start_pass = start_pass_fdctmgr;
+
+  switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+  case JDCT_ISLOW:
+    lossyc->fdct_forward_DCT = forward_DCT;
+    fdct->do_dct = jpeg_fdct_islow;
+    break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+  case JDCT_IFAST:
+    lossyc->fdct_forward_DCT = forward_DCT;
+    fdct->do_dct = jpeg_fdct_ifast;
+    break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+  case JDCT_FLOAT:
+    lossyc->fdct_forward_DCT = forward_DCT_float;
+    fdct->do_float_dct = jpeg_fdct_float;
+    break;
+#endif
+  default:
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+    break;
+  }
+
+  /* Mark divisor tables unallocated */
+  for (i = 0; i < NUM_QUANT_TBLS; i++) {
+    fdct->divisors[i] = NULL;
+#ifdef DCT_FLOAT_SUPPORTED
+    fdct->float_divisors[i] = NULL;
+#endif
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcdiffct.c b/Utilities/ITK/Utilities/itkjpeg/jcdiffct.c
new file mode 100644
index 0000000000000000000000000000000000000000..d3953425c259f936c862c1205137d2c738d26b20
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcdiffct.c
@@ -0,0 +1,410 @@
+/*
+ * jcdiffct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the difference buffer controller for compression.
+ * This controller is the top level of the lossless JPEG compressor proper.
+ * The difference buffer lies between prediction/differencing and entropy
+ * encoding.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossls.h"    /* Private declarations for lossless codec */
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+/* We use a full-image sample buffer when doing Huffman optimization,
+ * and also for writing multiple-scan JPEG files.  In all cases, the
+ * full-image buffer is filled during the first pass, and the scaling,
+ * prediction and differencing steps are run during subsequent passes.
+ */
+#ifdef ENTROPY_OPT_SUPPORTED
+#define FULL_SAMP_BUFFER_SUPPORTED
+#else
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+#define FULL_SAMP_BUFFER_SUPPORTED
+#endif
+#endif
+
+
+/* Private buffer controller object */
+
+typedef struct {
+  JDIMENSION iMCU_row_num;  /* iMCU row # within image */
+  JDIMENSION mcu_ctr;    /* counts MCUs processed in current row */
+  int MCU_vert_offset;    /* counts MCU rows within iMCU row */
+  int MCU_rows_per_iMCU_row;  /* number of such rows needed */
+
+  JSAMPROW cur_row[MAX_COMPONENTS];  /* row of point transformed samples */
+  JSAMPROW prev_row[MAX_COMPONENTS];  /* previous row of Pt'd samples */
+  JDIFFARRAY diff_buf[MAX_COMPONENTS];  /* iMCU row of differences */
+
+  /* In multi-pass modes, we need a virtual sample array for each component. */
+  jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
+} c_diff_controller;
+
+typedef c_diff_controller * c_diff_ptr;
+
+
+/* Forward declarations */
+METHODDEF(boolean) compress_data
+    JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#ifdef FULL_SAMP_BUFFER_SUPPORTED
+METHODDEF(boolean) compress_first_pass
+    JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+METHODDEF(boolean) compress_output
+    JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_compress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row */
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
+
+  /* In an interleaved scan, an MCU row is the same as an iMCU row.
+   * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+   * But at the bottom of the image, process only what's left.
+   */
+  if (cinfo->comps_in_scan > 1) {
+    diff->MCU_rows_per_iMCU_row = 1;
+  } else {
+    if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+      diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+    else
+      diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+  }
+
+  diff->mcu_ctr = 0;
+  diff->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_diff (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
+
+  diff->iMCU_row_num = 0;
+  start_iMCU_row(cinfo);
+
+  switch (pass_mode) {
+  case JBUF_PASS_THRU:
+    if (diff->whole_image[0] != NULL)
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    losslsc->pub.compress_data = compress_data;
+    break;
+#ifdef FULL_SAMP_BUFFER_SUPPORTED
+  case JBUF_SAVE_AND_PASS:
+    if (diff->whole_image[0] == NULL)
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    losslsc->pub.compress_data = compress_first_pass;
+    break;
+  case JBUF_CRANK_DEST:
+    if (diff->whole_image[0] == NULL)
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    losslsc->pub.compress_data = compress_output;
+    break;
+#endif
+  default:
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    break;
+  }
+}
+
+
+#define SWAP_ROWS(rowa,rowb) {JSAMPROW temp; temp=rowa; rowa=rowb; rowb=temp;}
+
+/*
+ * Process some data in the single-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor rows for each component in the image.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(boolean)
+compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
+  JDIMENSION MCU_col_num;  /* index of current MCU within row */
+  JDIMENSION MCU_count;    /* number of MCUs encoded */
+  /* JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; */
+  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+  int comp, ci, yoffset, samp_row, samp_rows, samps_across;
+  jpeg_component_info *compptr;
+
+  /* Loop to write as much as one whole iMCU row */
+  for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row;
+       yoffset++) {
+
+    MCU_col_num = diff->mcu_ctr;
+
+    /* Scale and predict each scanline of the MCU-row separately.
+     *
+     * Note: We only do this if we are at the start of a MCU-row, ie,
+     * we don't want to reprocess a row suspended by the output.
+     */
+    if (MCU_col_num == 0) {
+      for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
+  compptr = cinfo->cur_comp_info[comp];
+  ci = compptr->component_index;
+  if (diff->iMCU_row_num < last_iMCU_row)
+    samp_rows = compptr->v_samp_factor;
+  else {
+    /* NB: can't use last_row_height here, since may not be set! */
+    samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+    if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
+    else {
+      /* Fill dummy difference rows at the bottom edge with zeros, which
+       * will encode to the smallest amount of data.
+       */
+      for (samp_row = samp_rows; samp_row < compptr->v_samp_factor;
+     samp_row++)
+        MEMZERO(diff->diff_buf[ci][samp_row],
+          jround_up((long) compptr->width_in_data_units,
+        (long) compptr->h_samp_factor) * SIZEOF(JDIFF));
+    }
+  }
+  samps_across = compptr->width_in_data_units;
+
+  for (samp_row = 0; samp_row < samp_rows; samp_row++) {
+    (*losslsc->scaler_scale) (cinfo,
+            input_buf[ci][samp_row],
+            diff->cur_row[ci], samps_across);
+    (*losslsc->predict_difference[ci]) (cinfo, ci,
+                diff->cur_row[ci],
+                diff->prev_row[ci],
+                diff->diff_buf[ci][samp_row],
+                samps_across);
+    SWAP_ROWS(diff->cur_row[ci], diff->prev_row[ci]);
+  }
+      }
+    }
+
+    /* Try to write the MCU-row (or remaining portion of suspended MCU-row). */
+    MCU_count =
+      (*losslsc->entropy_encode_mcus) (cinfo,
+               diff->diff_buf, yoffset, MCU_col_num,
+               cinfo->MCUs_per_row - MCU_col_num);
+    if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) {
+      /* Suspension forced; update state counters and exit */
+      diff->MCU_vert_offset = yoffset;
+      diff->mcu_ctr += MCU_col_num;
+      return FALSE;
+    }
+
+    /* Completed an MCU row, but perhaps not an iMCU row */
+    diff->mcu_ctr = 0;
+  }
+
+  /* Completed the iMCU row, advance counters for next one */
+  diff->iMCU_row_num++;
+  start_iMCU_row(cinfo);
+  return TRUE;
+}
+
+
+#ifdef FULL_SAMP_BUFFER_SUPPORTED
+
+/*
+ * Process some data in the first pass of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor rows for each component in the image.
+ * This amount of data is read from the source buffer and saved into the
+ * virtual arrays.
+ *
+ * We must also emit the data to the compressor.  This is conveniently
+ * done by calling compress_output() after we've loaded the current strip
+ * of the virtual arrays.
+ *
+ * NB: input_buf contains a plane for each component in image.  All components
+ * are loaded into the virtual arrays in this pass.  However, it may be that
+ * only a subset of the components are emitted to the compressor during
+ * this first pass; be careful about looking at the scan-dependent variables
+ * (MCU dimensions, etc).
+ */
+
+METHODDEF(boolean)
+compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
+  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+  JDIMENSION samps_across;
+  int ci, samp_row, samp_rows;
+  JSAMPARRAY buffer[MAX_COMPONENTS];
+  jpeg_component_info *compptr;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Align the virtual buffers for this component. */
+    buffer[ci] = (*cinfo->mem->access_virt_sarray)
+      ((j_common_ptr) cinfo, diff->whole_image[ci],
+       diff->iMCU_row_num * compptr->v_samp_factor,
+       (JDIMENSION) compptr->v_samp_factor, TRUE);
+
+    /* Count non-dummy sample rows in this iMCU row. */
+    if (diff->iMCU_row_num < last_iMCU_row)
+      samp_rows = compptr->v_samp_factor;
+    else {
+      /* NB: can't use last_row_height here, since may not be set! */
+      samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+      if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
+    }
+    samps_across = compptr->width_in_data_units;
+
+    /* Perform point transform scaling and prediction/differencing for all
+     * non-dummy rows in this iMCU row.  Each call on these functions
+     * process a complete row of samples.
+     */
+    for (samp_row = 0; samp_row < samp_rows; samp_row++) {
+      MEMCOPY(buffer[ci][samp_row], input_buf[ci][samp_row],
+        samps_across * SIZEOF(JSAMPLE));
+    }
+  }
+
+  /* NB: compress_output will increment iMCU_row_num if successful.
+   * A suspension return will result in redoing all the work above next time.
+   */
+
+  /* Emit data to the compressor, sharing code with subsequent passes */
+  return compress_output(cinfo, input_buf);
+}
+
+
+/*
+ * Process some data in subsequent passes of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor rows for each component in the scan.
+ * The data is obtained from the virtual arrays and fed to the compressor.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf is ignored; it is likely to be a NULL pointer.
+ */
+
+METHODDEF(boolean)
+compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
+  /* JDIMENSION MCU_col_num; */  /* index of current MCU within row */
+  /* JDIMENSION MCU_count; */  /* number of MCUs encoded */
+  int comp, ci /* , yoffset */ ;
+  JSAMPARRAY buffer[MAX_COMPONENTS];
+  jpeg_component_info *compptr;
+  (void)input_buf;
+
+  /* Align the virtual buffers for the components used in this scan.
+   * NB: during first pass, this is safe only because the buffers will
+   * already be aligned properly, so jmemmgr.c won't need to do any I/O.
+   */
+  for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
+    compptr = cinfo->cur_comp_info[comp];
+    ci = compptr->component_index;
+    buffer[ci] = (*cinfo->mem->access_virt_sarray)
+      ((j_common_ptr) cinfo, diff->whole_image[ci],
+       diff->iMCU_row_num * compptr->v_samp_factor,
+       (JDIMENSION) compptr->v_samp_factor, FALSE);
+  }
+
+  return compress_data(cinfo, buffer);
+}
+
+#endif /* FULL_SAMP_BUFFER_SUPPORTED */
+
+
+/*
+ * Initialize difference buffer controller.
+ */
+
+GLOBAL(void)
+jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  c_diff_ptr diff;
+  int ci, row;
+  jpeg_component_info *compptr;
+
+  diff = (c_diff_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(c_diff_controller));
+  losslsc->diff_private = (void *) diff;
+  losslsc->diff_start_pass = start_pass_diff;
+
+  /* Create the prediction row buffers. */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    diff->cur_row[ci] = *(*cinfo->mem->alloc_sarray)
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+            (long) compptr->h_samp_factor),
+       (JDIMENSION) 1);
+    diff->prev_row[ci] = *(*cinfo->mem->alloc_sarray)
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+            (long) compptr->h_samp_factor),
+       (JDIMENSION) 1);
+  }
+
+  /* Create the difference buffer. */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    diff->diff_buf[ci] = (*cinfo->mem->alloc_darray)
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+            (long) compptr->h_samp_factor),
+       (JDIMENSION) compptr->v_samp_factor);
+    /* Prefill difference rows with zeros.  We do this because only actual
+     * data is placed in the buffers during prediction/differencing, leaving
+     * any dummy differences at the right edge as zeros, which will encode
+     * to the smallest amount of data.
+     */
+    for (row = 0; row < compptr->v_samp_factor; row++)
+      MEMZERO(diff->diff_buf[ci][row],
+        jround_up((long) compptr->width_in_data_units,
+      (long) compptr->h_samp_factor) * SIZEOF(JDIFF));
+  }
+
+  /* Create the sample buffer. */
+  if (need_full_buffer) {
+#ifdef FULL_SAMP_BUFFER_SUPPORTED
+    /* Allocate a full-image virtual array for each component, */
+    /* padded to a multiple of samp_factor differences in each direction. */
+    int ci;
+    jpeg_component_info *compptr;
+
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
+  ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+   (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+        (long) compptr->h_samp_factor),
+   (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+        (long) compptr->v_samp_factor),
+   (JDIMENSION) compptr->v_samp_factor);
+    }
+#else
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+  } else
+    diff->whole_image[0] = NULL; /* flag for no virtual arrays */
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jchuff.c b/Utilities/ITK/Utilities/itkjpeg/jchuff.c
new file mode 100644
index 0000000000000000000000000000000000000000..86683b14e4971e6a41f1872c1d16f078b01159e2
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jchuff.c
@@ -0,0 +1,274 @@
+/*
+ * jchuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines which are shared
+ * by the sequential, progressive and lossless decoders.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jchuff.h"    /* Declarations shared with jc*huff.c */
+
+
+/*
+ * Compute the derived values for a Huffman table.
+ * This routine also performs some validation checks on the table.
+ */
+
+GLOBAL(void)
+jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
+       c_derived_tbl ** pdtbl)
+{
+  JHUFF_TBL *htbl;
+  c_derived_tbl *dtbl;
+  int p, i, l, lastp, si, maxsymbol;
+  char huffsize[257];
+  unsigned int huffcode[257];
+  unsigned int code;
+
+  /* Note that huffsize[] and huffcode[] are filled in code-length order,
+   * paralleling the order of the symbols themselves in htbl->huffval[].
+   */
+
+  /* Find the input Huffman table */
+  if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
+    ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+  htbl =
+    isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
+  if (htbl == NULL)
+    ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+
+  /* Allocate a workspace if we haven't already done so. */
+  if (*pdtbl == NULL)
+    *pdtbl = (c_derived_tbl *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          SIZEOF(c_derived_tbl));
+  dtbl = *pdtbl;
+  
+  /* Figure C.1: make table of Huffman code length for each symbol */
+
+  p = 0;
+  for (l = 1; l <= 16; l++) {
+    i = (int) htbl->bits[l];
+    if (i < 0 || p + i > 256)  /* protect against table overrun */
+      ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+    while (i--)
+      huffsize[p++] = (char) l;
+  }
+  huffsize[p] = 0;
+  lastp = p;
+  
+  /* Figure C.2: generate the codes themselves */
+  /* We also validate that the counts represent a legal Huffman code tree. */
+
+  code = 0;
+  si = huffsize[0];
+  p = 0;
+  while (huffsize[p]) {
+    while (((int) huffsize[p]) == si) {
+      huffcode[p++] = code;
+      code++;
+    }
+    /* code is now 1 more than the last code used for codelength si; but
+     * it must still fit in si bits, since no code is allowed to be all ones.
+     * BUG FIX 2001-09-03: Comparison must be >, not >=
+     */
+    if (((INT32) code) > (((INT32) 1) << si))
+      ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+    code <<= 1;
+    si++;
+  }
+  
+  /* Figure C.3: generate encoding tables */
+  /* These are code and size indexed by symbol value */
+
+  /* Set all codeless symbols to have code length 0;
+   * this lets us detect duplicate VAL entries here, and later
+   * allows emit_bits to detect any attempt to emit such symbols.
+   */
+  MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi));
+
+  /* This is also a convenient place to check for out-of-range
+   * and duplicated VAL entries.  We allow 0..255 for AC symbols
+   * but only 0..16 for DC.  (We could constrain them further
+   * based on data depth and mode, but this seems enough.)
+   */
+  maxsymbol = isDC ? 16 : 255;
+
+  for (p = 0; p < lastp; p++) {
+    i = htbl->huffval[p];
+    if (i < 0 || i > maxsymbol || dtbl->ehufsi[i])
+      ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+    dtbl->ehufco[i] = huffcode[p];
+    dtbl->ehufsi[i] = huffsize[p];
+  }
+}
+
+
+/*
+ * Generate the best Huffman code table for the given counts, fill htbl.
+ *
+ * The JPEG standard requires that no symbol be assigned a codeword of all
+ * one bits (so that padding bits added at the end of a compressed segment
+ * can't look like a valid code).  Because of the canonical ordering of
+ * codewords, this just means that there must be an unused slot in the
+ * longest codeword length category.  Section K.2 of the JPEG spec suggests
+ * reserving such a slot by pretending that symbol 256 is a valid symbol
+ * with count 1.  In theory that's not optimal; giving it count zero but
+ * including it in the symbol set anyway should give a better Huffman code.
+ * But the theoretically better code actually seems to come out worse in
+ * practice, because it produces more all-ones bytes (which incur stuffed
+ * zero bytes in the final file).  In any case the difference is tiny.
+ *
+ * The JPEG standard requires Huffman codes to be no more than 16 bits long.
+ * If some symbols have a very small but nonzero probability, the Huffman tree
+ * must be adjusted to meet the code length restriction.  We currently use
+ * the adjustment method suggested in JPEG section K.2.  This method is *not*
+ * optimal; it may not choose the best possible limited-length code.  But
+ * typically only very-low-frequency symbols will be given less-than-optimal
+ * lengths, so the code is almost optimal.  Experimental comparisons against
+ * an optimal limited-length-code algorithm indicate that the difference is
+ * microscopic --- usually less than a hundredth of a percent of total size.
+ * So the extra complexity of an optimal algorithm doesn't seem worthwhile.
+ */
+
+GLOBAL(void)
+jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])
+{
+#define MAX_CLEN 32    /* assumed maximum initial code length */
+  UINT8 bits[MAX_CLEN+1];  /* bits[k] = # of symbols with code length k */
+  int codesize[257];    /* codesize[k] = code length of symbol k */
+  int others[257];    /* next symbol in current branch of tree */
+  int c1, c2;
+  int p, i, j;
+  long v;
+
+  /* This algorithm is explained in section K.2 of the JPEG standard */
+
+  MEMZERO(bits, SIZEOF(bits));
+  MEMZERO(codesize, SIZEOF(codesize));
+  for (i = 0; i < 257; i++)
+    others[i] = -1;    /* init links to empty */
+  
+  freq[256] = 1;    /* make sure 256 has a nonzero count */
+  /* Including the pseudo-symbol 256 in the Huffman procedure guarantees
+   * that no real symbol is given code-value of all ones, because 256
+   * will be placed last in the largest codeword category.
+   */
+
+  /* Huffman's basic algorithm to assign optimal code lengths to symbols */
+
+  for (;;) {
+    /* Find the smallest nonzero frequency, set c1 = its symbol */
+    /* In case of ties, take the larger symbol number */
+    c1 = -1;
+    v = 1000000000L;
+    for (i = 0; i <= 256; i++) {
+      if (freq[i] && freq[i] <= v) {
+  v = freq[i];
+  c1 = i;
+      }
+    }
+
+    /* Find the next smallest nonzero frequency, set c2 = its symbol */
+    /* In case of ties, take the larger symbol number */
+    c2 = -1;
+    v = 1000000000L;
+    for (i = 0; i <= 256; i++) {
+      if (freq[i] && freq[i] <= v && i != c1) {
+  v = freq[i];
+  c2 = i;
+      }
+    }
+
+    /* Done if we've merged everything into one frequency */
+    if (c2 < 0)
+      break;
+    
+    /* Else merge the two counts/trees */
+    freq[c1] += freq[c2];
+    freq[c2] = 0;
+
+    /* Increment the codesize of everything in c1's tree branch */
+    codesize[c1]++;
+    while (others[c1] >= 0) {
+      c1 = others[c1];
+      codesize[c1]++;
+    }
+    
+    others[c1] = c2;    /* chain c2 onto c1's tree branch */
+    
+    /* Increment the codesize of everything in c2's tree branch */
+    codesize[c2]++;
+    while (others[c2] >= 0) {
+      c2 = others[c2];
+      codesize[c2]++;
+    }
+  }
+
+  /* Now count the number of symbols of each code length */
+  for (i = 0; i <= 256; i++) {
+    if (codesize[i]) {
+      /* The JPEG standard seems to think that this can't happen, */
+      /* but I'm paranoid... */
+      if (codesize[i] > MAX_CLEN)
+  ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW);
+
+      bits[codesize[i]]++;
+    }
+  }
+
+  /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
+   * Huffman procedure assigned any such lengths, we must adjust the coding.
+   * Here is what the JPEG spec says about how this next bit works:
+   * Since symbols are paired for the longest Huffman code, the symbols are
+   * removed from this length category two at a time.  The prefix for the pair
+   * (which is one bit shorter) is allocated to one of the pair; then,
+   * skipping the BITS entry for that prefix length, a code word from the next
+   * shortest nonzero BITS entry is converted into a prefix for two code words
+   * one bit longer.
+   */
+  
+  for (i = MAX_CLEN; i > 16; i--) {
+    while (bits[i] > 0) {
+      j = i - 2;    /* find length of new prefix to be used */
+      while (bits[j] == 0)
+  j--;
+      
+      bits[i] -= 2;    /* remove two symbols */
+      bits[i-1]++;    /* one goes in this length */
+      bits[j+1] += 2;    /* two new symbols in this length */
+      bits[j]--;    /* symbol of this length is now a prefix */
+    }
+  }
+
+  /* Remove the count for the pseudo-symbol 256 from the largest codelength */
+  while (bits[i] == 0)    /* find largest codelength still in use */
+    i--;
+  bits[i]--;
+  
+  /* Return final symbol counts (only for lengths 0..16) */
+  MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits));
+  
+  /* Return a list of the symbols sorted by code length */
+  /* It's not real clear to me why we don't need to consider the codelength
+   * changes made above, but the JPEG spec seems to think this works.
+   */
+  p = 0;
+  for (i = 1; i <= MAX_CLEN; i++) {
+    for (j = 0; j <= 255; j++) {
+      if (codesize[j] == i) {
+  htbl->huffval[p] = (UINT8) j;
+  p++;
+      }
+    }
+  }
+
+  /* Set sent_table FALSE so updated table will be written to JPEG file. */
+  htbl->sent_table = FALSE;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jchuff.h b/Utilities/ITK/Utilities/itkjpeg/jchuff.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b0570ea4b88ec53dac42454277911c4d2d0beeb
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jchuff.h
@@ -0,0 +1,54 @@
+/*
+ * jchuff.h
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains declarations for Huffman entropy encoding routines
+ * that are shared between the sequential encoder (jchuff.c) and the
+ * progressive encoder (jcphuff.c).  No other modules need to see these.
+ */
+
+/* The legal range of a DCT coefficient is
+ *  -1024 .. +1023  for 8-bit data;
+ * -16384 .. +16383 for 12-bit data.
+ * Hence the magnitude should always fit in 10 or 14 bits respectively.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MAX_COEF_BITS 10
+#else
+#define MAX_COEF_BITS 14
+#endif
+
+/* The legal range of a spatial difference is
+ * -32767 .. +32768.
+ * Hence the magnitude should always fit in 16 bits.
+ */
+
+#define MAX_DIFF_BITS 16
+
+/* Derived data constructed for each Huffman table */
+
+typedef struct {
+  unsigned int ehufco[256];  /* code for each symbol */
+  char ehufsi[256];    /* length of code for each symbol */
+  /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */
+} c_derived_tbl;
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_make_c_derived_tbl  jMkCDerived
+#define jpeg_gen_optimal_table  jGenOptTbl
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+/* Expand a Huffman table definition into the derived format */
+EXTERN(void) jpeg_make_c_derived_tbl
+  JPP((j_compress_ptr cinfo, boolean isDC, int tblno,
+       c_derived_tbl ** pdtbl));
+
+/* Generate an optimal table definition given the specified counts */
+EXTERN(void) jpeg_gen_optimal_table
+  JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]));
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcinit.c b/Utilities/ITK/Utilities/itkjpeg/jcinit.c
new file mode 100644
index 0000000000000000000000000000000000000000..b485a8e7e43a3fbcbbb2016c7de2305ee264f688
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcinit.c
@@ -0,0 +1,57 @@
+/*
+ * jcinit.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains initialization logic for the JPEG compressor.
+ * This routine is in charge of selecting the modules to be executed and
+ * making an initialization call to each one.
+ *
+ * Logically, this code belongs in jcmaster.c.  It's split out because
+ * linking this routine implies linking the entire compression library.
+ * For a transcoding-only application, we want to be able to use jcmaster.c
+ * without linking in the whole library.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Master selection of compression modules.
+ * This is done once at the start of processing an image.  We determine
+ * which modules will be used and give them appropriate initialization calls.
+ */
+
+GLOBAL(void)
+jinit_compress_master (j_compress_ptr cinfo)
+{
+  /* Initialize master control (includes parameter checking/processing) */
+  jinit_c_master_control(cinfo, FALSE /* full compression */);
+
+  /* Initialize compression codec */
+  jinit_c_codec(cinfo);
+
+  /* Preprocessing */
+  if (! cinfo->raw_data_in) {
+    jinit_color_converter(cinfo);
+    jinit_downsampler(cinfo);
+    jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
+  }
+
+  jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
+
+  jinit_marker_writer(cinfo);
+
+  /* We can now tell the memory manager to allocate virtual arrays. */
+  (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+  /* Write the datastream header (SOI) immediately.
+   * Frame and scan headers are postponed till later.
+   * This lets application insert special markers after the SOI.
+   */
+  (*cinfo->marker->write_file_header) (cinfo);
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jclhuff.c b/Utilities/ITK/Utilities/itkjpeg/jclhuff.c
new file mode 100644
index 0000000000000000000000000000000000000000..a553ccee4ad48f48dab7fbe3ef10d2d18f3a3fd0
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jclhuff.c
@@ -0,0 +1,602 @@
+/*
+ * jclhuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy encoding routines for lossless JPEG.
+ *
+ * Much of the complexity here has to do with supporting output suspension.
+ * If the data destination module demands suspension, we want to be able to
+ * back up to the start of the current MCU.  To do this, we copy state
+ * variables into local working storage, and update them back to the
+ * permanent JPEG objects only upon successful completion of an MCU.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossls.h"    /* Private declarations for lossless codec */
+#include "jchuff.h"    /* Declarations shared with jc*huff.c */
+
+
+/* Expanded entropy encoder object for Huffman encoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+  INT32 put_buffer;    /* current bit-accumulation buffer */
+  int put_bits;      /* # of bits now in it */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment.  You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src)  ((dest) = (src))
+#else
+#define ASSIGN_STATE(dest,src)  \
+  ((dest).put_buffer = (src).put_buffer, \
+   (dest).put_bits = (src).put_bits)
+#endif
+
+
+typedef struct {
+  int ci, yoffset, MCU_width;
+} lhe_input_ptr_info;
+
+
+typedef struct {
+  savable_state saved;    /* Bit buffer at start of MCU */
+
+  /* These fields are NOT loaded into local working state. */
+  unsigned int restarts_to_go;  /* MCUs left in this restart interval */
+  int next_restart_num;    /* next restart number to write (0-7) */
+
+  /* Pointers to derived tables (these workspaces have image lifespan) */
+  c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+  /* Pointers to derived tables to be used for each data unit within an MCU */
+  c_derived_tbl * cur_tbls[C_MAX_DATA_UNITS_IN_MCU];
+
+#ifdef ENTROPY_OPT_SUPPORTED  /* Statistics tables for optimization */
+  long * count_ptrs[NUM_HUFF_TBLS];
+
+  /* Pointers to stats tables to be used for each data unit within an MCU */
+  long * cur_counts[C_MAX_DATA_UNITS_IN_MCU];
+#endif
+
+  /* Pointers to the proper input difference row for each group of data units
+   * within an MCU.  For each component, there are Vi groups of Hi data units.
+   */
+  JDIFFROW input_ptr[C_MAX_DATA_UNITS_IN_MCU];
+
+  /* Number of input pointers in use for the current MCU.  This is the sum
+   * of all Vi in the MCU.
+   */
+  int num_input_ptrs;
+
+  /* Information used for positioning the input pointers within the input
+   * difference rows.
+   */
+  lhe_input_ptr_info input_ptr_info[C_MAX_DATA_UNITS_IN_MCU];
+
+  /* Index of the proper input pointer for each data unit within an MCU */
+  int input_ptr_index[C_MAX_DATA_UNITS_IN_MCU];
+
+} lhuff_entropy_encoder;
+
+typedef lhuff_entropy_encoder * lhuff_entropy_ptr;
+
+/* Working state while writing an MCU.
+ * This struct contains all the fields that are needed by subroutines.
+ */
+
+typedef struct {
+  JOCTET * next_output_byte;  /* => next byte to write in buffer */
+  size_t free_in_buffer;  /* # of byte spaces remaining in buffer */
+  savable_state cur;    /* Current bit buffer & DC state */
+  j_compress_ptr cinfo;    /* dump_buffer needs access to this */
+} working_state;
+
+
+/* Forward declarations */
+METHODDEF(JDIMENSION) encode_mcus_huff (j_compress_ptr cinfo,
+          JDIFFIMAGE diff_buf,
+          JDIMENSION MCU_row_num,
+          JDIMENSION MCU_col_num,
+          JDIMENSION nMCU);
+METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo));
+#ifdef ENTROPY_OPT_SUPPORTED
+METHODDEF(JDIMENSION) encode_mcus_gather (j_compress_ptr cinfo,
+            JDIFFIMAGE diff_buf,
+            JDIMENSION MCU_row_num,
+            JDIMENSION MCU_col_num,
+            JDIMENSION nMCU);
+METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo));
+#endif
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ * If gather_statistics is TRUE, we do not output anything during the scan,
+ * just count the Huffman symbols used and generate Huffman code tables.
+ */
+
+METHODDEF(void)
+start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
+  int ci, dctbl, sampn, ptrn, yoffset, xoffset;
+  jpeg_component_info * compptr;
+
+  if (gather_statistics) {
+#ifdef ENTROPY_OPT_SUPPORTED
+    losslsc->entropy_encode_mcus = encode_mcus_gather;
+    losslsc->pub.entropy_finish_pass = finish_pass_gather;
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+  } else {
+    losslsc->entropy_encode_mcus = encode_mcus_huff;
+    losslsc->pub.entropy_finish_pass = finish_pass_huff;
+  }
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    dctbl = compptr->dc_tbl_no;
+    if (gather_statistics) {
+#ifdef ENTROPY_OPT_SUPPORTED
+      /* Check for invalid table indexes */
+      /* (make_c_derived_tbl does this in the other path) */
+      if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS)
+  ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
+      /* Allocate and zero the statistics tables */
+      /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
+      if (entropy->count_ptrs[dctbl] == NULL)
+  entropy->count_ptrs[dctbl] = (long *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+              257 * SIZEOF(long));
+      MEMZERO(entropy->count_ptrs[dctbl], 257 * SIZEOF(long));
+#endif
+    } else {
+      /* Compute derived values for Huffman tables */
+      /* We may do this more than once for a table, but it's not expensive */
+      jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
+            & entropy->derived_tbls[dctbl]);
+    }
+  }
+
+  /* Precalculate encoding info for each sample in an MCU of this scan */
+  for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) {
+    compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]];
+    ci = compptr->component_index;
+    /*    ci = cinfo->MCU_membership[sampn];
+    compptr = cinfo->cur_comp_info[ci];*/
+    for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) {
+      /* Precalculate the setup info for each input pointer */
+      entropy->input_ptr_info[ptrn].ci = ci;
+      entropy->input_ptr_info[ptrn].yoffset = yoffset;
+      entropy->input_ptr_info[ptrn].MCU_width = compptr->MCU_width;
+      for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) {
+  /* Precalculate the input pointer index for each sample */
+  entropy->input_ptr_index[sampn] = ptrn;
+  /* Precalculate which tables to use for each sample */
+  entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no];
+  entropy->cur_counts[sampn] = entropy->count_ptrs[compptr->dc_tbl_no];
+      }
+    }
+  }
+  entropy->num_input_ptrs = ptrn;
+
+  /* Initialize bit buffer to empty */
+  entropy->saved.put_buffer = 0;
+  entropy->saved.put_bits = 0;
+
+  /* Initialize restart stuff */
+  entropy->restarts_to_go = cinfo->restart_interval;
+  entropy->next_restart_num = 0;
+}
+
+
+/* Outputting bytes to the file */
+
+/* Emit a byte, taking 'action' if must suspend. */
+#define emit_byte(state,val,action)  \
+  { *(state)->next_output_byte++ = (JOCTET) (val);  \
+    if (--(state)->free_in_buffer == 0)  \
+      if (! dump_buffer(state))  \
+        { action; } }
+
+
+LOCAL(boolean)
+dump_buffer (working_state * state)
+/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
+{
+  struct jpeg_destination_mgr * dest = state->cinfo->dest;
+
+  if (! (*dest->empty_output_buffer) (state->cinfo))
+    return FALSE;
+  /* After a successful buffer dump, must reset buffer pointers */
+  state->next_output_byte = dest->next_output_byte;
+  state->free_in_buffer = dest->free_in_buffer;
+  return TRUE;
+}
+
+
+/* Outputting bits to the file */
+
+/* Only the right 24 bits of put_buffer are used; the valid bits are
+ * left-justified in this part.  At most 16 bits can be passed to emit_bits
+ * in one call, and we never retain more than 7 bits in put_buffer
+ * between calls, so 24 bits are sufficient.
+ */
+
+INLINE
+LOCAL(boolean)
+emit_bits (working_state * state, unsigned int code, int size)
+/* Emit some bits; return TRUE if successful, FALSE if must suspend */
+{
+  /* This routine is heavily used, so it's worth coding tightly. */
+  register INT32 put_buffer = (INT32) code;
+  register int put_bits = state->cur.put_bits;
+
+  /* if size is 0, caller used an invalid Huffman table entry */
+  if (size == 0)
+    ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE);
+
+  put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+  
+  put_bits += size;    /* new number of bits in buffer */
+  
+  put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+  put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
+  
+  while (put_bits >= 8) {
+    int c = (int) ((put_buffer >> 16) & 0xFF);
+    
+    emit_byte(state, c, return FALSE);
+    if (c == 0xFF) {    /* need to stuff a zero byte? */
+      emit_byte(state, 0, return FALSE);
+    }
+    put_buffer <<= 8;
+    put_bits -= 8;
+  }
+
+  state->cur.put_buffer = put_buffer; /* update state variables */
+  state->cur.put_bits = put_bits;
+
+  return TRUE;
+}
+
+
+LOCAL(boolean)
+flush_bits (working_state * state)
+{
+  if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
+    return FALSE;
+  state->cur.put_buffer = 0;  /* and reset bit-buffer to empty */
+  state->cur.put_bits = 0;
+  return TRUE;
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL(boolean)
+emit_restart (working_state * state, int restart_num)
+{
+  /* int ci; */
+
+  if (! flush_bits(state))
+    return FALSE;
+
+  emit_byte(state, 0xFF, return FALSE);
+  emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
+
+  /* The restart counter is not updated until we successfully write the MCU. */
+
+  return TRUE;
+}
+
+
+/*
+ * Encode and output one nMCU's worth of Huffman-compressed differences.
+ */
+
+METHODDEF(JDIMENSION)
+encode_mcus_huff (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
+      JDIMENSION MCU_row_num, JDIMENSION MCU_col_num,
+      JDIMENSION nMCU)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
+  working_state state;
+  unsigned int mcu_num;
+  int sampn, ci, yoffset, MCU_width, ptrn;
+  /* jpeg_component_info * compptr; */
+
+  /* Load up working state */
+  state.next_output_byte = cinfo->dest->next_output_byte;
+  state.free_in_buffer = cinfo->dest->free_in_buffer;
+  ASSIGN_STATE(state.cur, entropy->saved);
+  state.cinfo = cinfo;
+
+  /* Emit restart marker if needed */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0)
+      if (! emit_restart(&state, entropy->next_restart_num))
+  return 0;
+  }
+
+  /* Set input pointer locations based on MCU_col_num */
+  for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) {
+    ci = entropy->input_ptr_info[ptrn].ci;
+    yoffset = entropy->input_ptr_info[ptrn].yoffset;
+    MCU_width = entropy->input_ptr_info[ptrn].MCU_width;
+    entropy->input_ptr[ptrn] =
+      diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
+  }
+
+  for (mcu_num = 0; mcu_num < nMCU; mcu_num++) {
+
+    /* Inner loop handles the samples in the MCU */
+    for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) {
+      register int temp, temp2 /* , temp3 */ ;
+      register int nbits;
+      c_derived_tbl *dctbl = entropy->cur_tbls[sampn];
+  
+      /* Encode the difference per section H.1.2.2 */
+  
+      /* Input the sample difference */
+      temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++;
+
+      if (temp & 0x8000) {  /* instead of temp < 0 */
+  temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */
+  if (temp == 0)    /* special case: magnitude = 32768 */
+    temp2 = temp = 0x8000;
+  temp2 = ~ temp;    /* one's complement of magnitude */
+      } else {
+  temp &= 0x7FFF;    /* abs value mod 2^16 */
+  temp2 = temp;    /* magnitude */
+      }
+
+      /* Find the number of bits needed for the magnitude of the difference */
+      nbits = 0;
+      while (temp) {
+  nbits++;
+  temp >>= 1;
+      }
+      /* Check for out-of-range difference values.
+       */
+      if (nbits > MAX_DIFF_BITS)
+  ERREXIT(cinfo, JERR_BAD_DIFF);
+  
+      /* Emit the Huffman-coded symbol for the number of bits */
+      if (! emit_bits(&state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
+  return mcu_num;
+
+      /* Emit that number of bits of the value, if positive, */
+      /* or the complement of its magnitude, if negative. */
+      if (nbits &&    /* emit_bits rejects calls with size 0 */
+    nbits != 16)    /* special case: no bits should be emitted */
+  if (! emit_bits(&state, (unsigned int) temp2, nbits))
+    return mcu_num;
+    }
+
+    /* Completed MCU, so update state */
+    cinfo->dest->next_output_byte = state.next_output_byte;
+    cinfo->dest->free_in_buffer = state.free_in_buffer;
+    ASSIGN_STATE(entropy->saved, state.cur);
+
+    /* Update restart-interval state too */
+    if (cinfo->restart_interval) {
+      if (entropy->restarts_to_go == 0) {
+  entropy->restarts_to_go = cinfo->restart_interval;
+  entropy->next_restart_num++;
+  entropy->next_restart_num &= 7;
+      }
+      entropy->restarts_to_go--;
+    }
+
+  }
+
+  return nMCU;
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+finish_pass_huff (j_compress_ptr cinfo)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
+  working_state state;
+
+  /* Load up working state ... flush_bits needs it */
+  state.next_output_byte = cinfo->dest->next_output_byte;
+  state.free_in_buffer = cinfo->dest->free_in_buffer;
+  ASSIGN_STATE(state.cur, entropy->saved);
+  state.cinfo = cinfo;
+
+  /* Flush out the last data */
+  if (! flush_bits(&state))
+    ERREXIT(cinfo, JERR_CANT_SUSPEND);
+
+  /* Update state */
+  cinfo->dest->next_output_byte = state.next_output_byte;
+  cinfo->dest->free_in_buffer = state.free_in_buffer;
+  ASSIGN_STATE(entropy->saved, state.cur);
+}
+
+
+/*
+ * Huffman coding optimization.
+ *
+ * We first scan the supplied data and count the number of uses of each symbol
+ * that is to be Huffman-coded. (This process MUST agree with the code above.)
+ * Then we build a Huffman coding tree for the observed counts.
+ * Symbols which are not needed at all for the particular image are not
+ * assigned any code, which saves space in the DHT marker as well as in
+ * the compressed data.
+ */
+
+#ifdef ENTROPY_OPT_SUPPORTED
+
+/*
+ * Trial-encode one nMCU's worth of Huffman-compressed differences.
+ * No data is actually output, so no suspension return is possible.
+ */
+
+METHODDEF(JDIMENSION)
+encode_mcus_gather (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
+        JDIMENSION MCU_row_num, JDIMENSION MCU_col_num,
+        JDIMENSION nMCU)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
+  unsigned int mcu_num; 
+  int sampn, ci, yoffset, MCU_width, ptrn;
+  /* jpeg_component_info * compptr; */
+
+  /* Take care of restart intervals if needed */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0) {
+      /* Update restart state */
+      entropy->restarts_to_go = cinfo->restart_interval;
+    }
+    entropy->restarts_to_go--;
+  }
+
+  /* Set input pointer locations based on MCU_col_num */
+  for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) {
+    ci = entropy->input_ptr_info[ptrn].ci;
+    yoffset = entropy->input_ptr_info[ptrn].yoffset;
+    MCU_width = entropy->input_ptr_info[ptrn].MCU_width;
+    entropy->input_ptr[ptrn] =
+      diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
+  }
+
+  for (mcu_num = 0; mcu_num < nMCU; mcu_num++) {
+
+    /* Inner loop handles the samples in the MCU */
+    for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) {
+      register int temp;
+      register int nbits;
+      /* c_derived_tbl *dctbl = entropy->cur_tbls[sampn]; */
+      long * counts = entropy->cur_counts[sampn];
+  
+      /* Encode the difference per section H.1.2.2 */
+  
+      /* Input the sample difference */
+      temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++;
+
+      if (temp & 0x8000) {  /* instead of temp < 0 */
+  temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */
+  if (temp == 0)    /* special case: magnitude = 32768 */
+    temp = 0x8000;
+      } else
+  temp &= 0x7FFF;    /* abs value mod 2^16 */
+
+      /* Find the number of bits needed for the magnitude of the difference */
+      nbits = 0;
+      while (temp) {
+  nbits++;
+  temp >>= 1;
+      }
+      /* Check for out-of-range difference values.
+       */
+      if (nbits > MAX_DIFF_BITS)
+  ERREXIT(cinfo, JERR_BAD_DIFF);
+  
+      /* Count the Huffman symbol for the number of bits */
+      counts[nbits]++;
+    }
+  }
+
+  return nMCU;
+}
+
+
+/*
+ * Finish up a statistics-gathering pass and create the new Huffman tables.
+ */
+
+METHODDEF(void)
+finish_pass_gather (j_compress_ptr cinfo)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
+  int ci, dctbl;
+  jpeg_component_info * compptr;
+  JHUFF_TBL **htblptr;
+  boolean did_dc[NUM_HUFF_TBLS];
+
+  /* It's important not to apply jpeg_gen_optimal_table more than once
+   * per table, because it clobbers the input frequency counts!
+   */
+  MEMZERO(did_dc, SIZEOF(did_dc));
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    dctbl = compptr->dc_tbl_no;
+    if (! did_dc[dctbl]) {
+      htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
+      if (*htblptr == NULL)
+  *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+      jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[dctbl]);
+      did_dc[dctbl] = TRUE;
+    }
+  }
+}
+
+
+#endif /* ENTROPY_OPT_SUPPORTED */
+
+
+METHODDEF(boolean)
+need_optimization_pass (j_compress_ptr cinfo)
+{
+  (void)cinfo;
+  return TRUE;
+}
+
+
+/*
+ * Module initialization routine for Huffman entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_lhuff_encoder (j_compress_ptr cinfo)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  lhuff_entropy_ptr entropy;
+  int i;
+
+  entropy = (lhuff_entropy_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(lhuff_entropy_encoder));
+  losslsc->entropy_private = (struct jpeg_entropy_encoder *) entropy;
+  losslsc->pub.entropy_start_pass = start_pass_huff;
+  losslsc->pub.need_optimization_pass = need_optimization_pass;
+
+  /* Mark tables unallocated */
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    entropy->derived_tbls[i] = NULL;
+#ifdef ENTROPY_OPT_SUPPORTED
+    entropy->count_ptrs[i] = NULL;
+#endif
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jclossls.c b/Utilities/ITK/Utilities/itkjpeg/jclossls.c
new file mode 100644
index 0000000000000000000000000000000000000000..34c952942b163351434822a2a3403979fa526301
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jclossls.c
@@ -0,0 +1,78 @@
+/*
+ * jclossls.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the control logic for the lossless JPEG compressor.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossls.h"
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+
+  (*losslsc->scaler_start_pass) (cinfo);
+  (*losslsc->predict_start_pass) (cinfo);
+  (*losslsc->diff_start_pass) (cinfo, pass_mode);
+}
+
+
+/*
+ * Initialize the lossless compression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void) 
+jinit_lossless_c_codec(j_compress_ptr cinfo)
+{
+  j_lossless_c_ptr losslsc;
+
+  /* Create subobject in permanent pool */
+  losslsc = (j_lossless_c_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+        SIZEOF(jpeg_lossless_c_codec));
+  cinfo->codec = (struct jpeg_c_codec *) losslsc;
+
+  /* Initialize sub-modules */
+
+  /* Scaler */
+  jinit_c_scaler(cinfo);
+
+  /* Differencer */
+  jinit_differencer(cinfo);
+
+  /* Entropy encoding: either Huffman or arithmetic coding. */
+  if (cinfo->arith_code) {
+    jinit_arith_encoder(cinfo);
+  } else {
+    jinit_lhuff_encoder(cinfo);
+  }
+
+  /* Need a full-image difference buffer in any multi-pass mode. */
+  jinit_c_diff_controller(cinfo,
+        (boolean) (cinfo->num_scans > 1 ||
+             cinfo->optimize_coding));
+
+  /* Initialize method pointers.
+   *
+   * Note: entropy_start_pass and entropy_finish_pass are assigned in
+   * jclhuff.c and compress_data is assigned in jcdiffct.c.
+   */
+  losslsc->pub.start_pass = start_pass;
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jclossy.c b/Utilities/ITK/Utilities/itkjpeg/jclossy.c
new file mode 100644
index 0000000000000000000000000000000000000000..4484714025e97379189e1f7319cac2a00369f60e
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jclossy.c
@@ -0,0 +1,76 @@
+/*
+ * jclossy.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the control logic for the lossy JPEG compressor.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+
+  (*lossyc->fdct_start_pass) (cinfo);
+  (*lossyc->coef_start_pass) (cinfo, pass_mode);
+}
+
+
+/*
+ * Initialize the lossy compression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void)
+jinit_lossy_c_codec (j_compress_ptr cinfo)
+{
+  j_lossy_c_ptr lossyc;
+
+  /* Create subobject in permanent pool */
+  lossyc = (j_lossy_c_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+        SIZEOF(jpeg_lossy_c_codec));
+  cinfo->codec = (struct jpeg_c_codec *) lossyc;
+
+  /* Initialize sub-modules */
+
+  /* Forward DCT */
+  jinit_forward_dct(cinfo);
+  /* Entropy encoding: either Huffman or arithmetic coding. */
+  if (cinfo->arith_code) {
+    jinit_arith_encoder(cinfo);
+  } else {
+    if (cinfo->process == JPROC_PROGRESSIVE) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+      jinit_phuff_encoder(cinfo);
+#else
+      ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+    } else
+      jinit_shuff_encoder(cinfo);
+  }
+
+  /* Need a full-image coefficient buffer in any multi-pass mode. */
+  jinit_c_coef_controller(cinfo,
+        (boolean) (cinfo->num_scans > 1 ||
+             cinfo->optimize_coding));
+
+  /* Initialize method pointers.
+   *
+   * Note: entropy_start_pass and entropy_finish_pass are assigned in
+   * jcshuff.c or jcphuff.c and compress_data is assigned in jccoefct.c.
+   */
+  lossyc->pub.start_pass = start_pass;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcmainct.c b/Utilities/ITK/Utilities/itkjpeg/jcmainct.c
new file mode 100644
index 0000000000000000000000000000000000000000..e0cd678a1973884d14ea7bab7e8c51a62cef5037
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcmainct.c
@@ -0,0 +1,296 @@
+/*
+ * jcmainct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the main buffer controller for compression.
+ * The main buffer lies between the pre-processor and the JPEG
+ * compressor proper; it holds downsampled data in the JPEG colorspace.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Note: currently, there is no operating mode in which a full-image buffer
+ * is needed at this step.  If there were, that mode could not be used with
+ * "raw data" input, since this module is bypassed in that case.  However,
+ * we've left the code here for possible use in special applications.
+ */
+#undef FULL_MAIN_BUFFER_SUPPORTED
+
+
+/* Private buffer controller object */
+
+typedef struct {
+  struct jpeg_c_main_controller pub; /* public fields */
+
+  JDIMENSION cur_iMCU_row;  /* number of current iMCU row */
+  JDIMENSION rowgroup_ctr;  /* counts row groups received in iMCU row */
+  boolean suspended;    /* remember if we suspended output */
+  J_BUF_MODE pass_mode;    /* current operating mode */
+
+  /* If using just a strip buffer, this points to the entire set of buffers
+   * (we allocate one for each component).  In the full-image case, this
+   * points to the currently accessible strips of the virtual arrays.
+   */
+  JSAMPARRAY buffer[MAX_COMPONENTS];
+
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+  /* If using full-image storage, this array holds pointers to virtual-array
+   * control blocks for each component.  Unused if not full-image storage.
+   */
+  jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
+#endif
+} my_main_controller;
+
+typedef my_main_controller * my_main_ptr;
+
+
+/* Forward declarations */
+METHODDEF(void) process_data_simple_main
+  JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
+       JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+METHODDEF(void) process_data_buffer_main
+  JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
+       JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
+#endif
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+  my_main_ptr mainPtr = (my_main_ptr) cinfo->main;
+
+  /* Do nothing in raw-data mode. */
+  if (cinfo->raw_data_in)
+    return;
+
+  mainPtr->cur_iMCU_row = 0;  /* initialize counters */
+  mainPtr->rowgroup_ctr = 0;
+  mainPtr->suspended = FALSE;
+  mainPtr->pass_mode = pass_mode;  /* save mode for use by process_data */
+
+  switch (pass_mode) {
+  case JBUF_PASS_THRU:
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+    if (mainPtr->whole_image[0] != NULL)
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+    mainPtr->pub.process_data = process_data_simple_main;
+    break;
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+  case JBUF_SAVE_SOURCE:
+  case JBUF_CRANK_DEST:
+  case JBUF_SAVE_AND_PASS:
+    if (mainPtr->whole_image[0] == NULL)
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    mainPtr->pub.process_data = process_data_buffer_main;
+    break;
+#endif
+  default:
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    break;
+  }
+}
+
+
+/*
+ * Process some data.
+ * This routine handles the simple pass-through mode,
+ * where we have only a strip buffer.
+ */
+
+METHODDEF(void)
+process_data_simple_main (j_compress_ptr cinfo,
+        JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+        JDIMENSION in_rows_avail)
+{
+  my_main_ptr mainPtr = (my_main_ptr) cinfo->main;
+  JDIMENSION data_unit = (JDIMENSION)(cinfo->data_unit);
+
+  while (mainPtr->cur_iMCU_row < cinfo->total_iMCU_rows) {
+    /* Read input data if we haven't filled the main buffer yet */
+    if (mainPtr->rowgroup_ctr < data_unit)
+      (*cinfo->prep->pre_process_data) (cinfo,
+          input_buf, in_row_ctr, in_rows_avail,
+          mainPtr->buffer, &mainPtr->rowgroup_ctr,
+          (JDIMENSION) data_unit);
+
+    /* If we don't have a full iMCU row buffered, return to application for
+     * more data.  Note that preprocessor will always pad to fill the iMCU row
+     * at the bottom of the image.
+     */
+    if (mainPtr->rowgroup_ctr != data_unit)
+      return;
+
+    /* Send the completed row to the compressor */
+    if (! (*cinfo->codec->compress_data) (cinfo, mainPtr->buffer)) {
+      /* If compressor did not consume the whole row, then we must need to
+       * suspend processing and return to the application.  In this situation
+       * we pretend we didn't yet consume the last input row; otherwise, if
+       * it happened to be the last row of the image, the application would
+       * think we were done.
+       */
+      if (! mainPtr->suspended) {
+  (*in_row_ctr)--;
+  mainPtr->suspended = TRUE;
+      }
+      return;
+    }
+    /* We did finish the row.  Undo our little suspension hack if a previous
+     * call suspended; then mark the main buffer empty.
+     */
+    if (mainPtr->suspended) {
+      (*in_row_ctr)++;
+      mainPtr->suspended = FALSE;
+    }
+    mainPtr->rowgroup_ctr = 0;
+    mainPtr->cur_iMCU_row++;
+  }
+}
+
+
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+
+/*
+ * Process some data.
+ * This routine handles all of the modes that use a full-size buffer.
+ */
+
+METHODDEF(void)
+process_data_buffer_main (j_compress_ptr cinfo,
+        JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+        JDIMENSION in_rows_avail)
+{
+  my_main_ptr main = (my_main_ptr) cinfo->main;
+  int ci;
+  jpeg_component_info *compptr;
+  boolean writing = (mainPtr->pass_mode != JBUF_CRANK_DEST);
+  JDIMENSION data_unit = (JDIMENSION)(cinfo->data_unit);
+
+  while (mainPtr->cur_iMCU_row < cinfo->total_iMCU_rows) {
+    /* Realign the virtual buffers if at the start of an iMCU row. */
+    if (mainPtr->rowgroup_ctr == 0) {
+      for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+     ci++, compptr++) {
+  mainPtr->buffer[ci] = (*cinfo->mem->access_virt_sarray)
+    ((j_common_ptr) cinfo, mainPtr->whole_image[ci],
+     mainPtr->cur_iMCU_row * (compptr->v_samp_factor * data_unit),
+     (JDIMENSION) (compptr->v_samp_factor * data_unit), writing);
+      }
+      /* In a read pass, pretend we just read some source data. */
+      if (! writing) {
+  *in_row_ctr += cinfo->max_v_samp_factor * data_unit;
+  mainPtr->rowgroup_ctr = data_unit;
+      }
+    }
+
+    /* If a write pass, read input data until the current iMCU row is full. */
+    /* Note: preprocessor will pad if necessary to fill the last iMCU row. */
+    if (writing) {
+      (*cinfo->prep->pre_process_data) (cinfo,
+          input_buf, in_row_ctr, in_rows_avail,
+          mainPtr->buffer, &mainPtr->rowgroup_ctr,
+          (JDIMENSION) data_unit);
+      /* Return to application if we need more data to fill the iMCU row. */
+      if (mainPtr->rowgroup_ctr < data_unit)
+  return;
+    }
+
+    /* Emit data, unless this is a sink-only pass. */
+    if (mainPtr->pass_mode != JBUF_SAVE_SOURCE) {
+      if (! (*cinfo->codec->compress_data) (cinfo, mainPtr->buffer)) {
+  /* If compressor did not consume the whole row, then we must need to
+   * suspend processing and return to the application.  In this situation
+   * we pretend we didn't yet consume the last input row; otherwise, if
+   * it happened to be the last row of the image, the application would
+   * think we were done.
+   */
+  if (! mainPtr->suspended) {
+    (*in_row_ctr)--;
+    mainPtr->suspended = TRUE;
+  }
+  return;
+      }
+      /* We did finish the row.  Undo our little suspension hack if a previous
+       * call suspended; then mark the main buffer empty.
+       */
+      if (mainPtr->suspended) {
+  (*in_row_ctr)++;
+  mainPtr->suspended = FALSE;
+      }
+    }
+
+    /* If get here, we are done with this iMCU row.  Mark buffer empty. */
+    mainPtr->rowgroup_ctr = 0;
+    mainPtr->cur_iMCU_row++;
+  }
+}
+
+#endif /* FULL_MAIN_BUFFER_SUPPORTED */
+
+
+/*
+ * Initialize main buffer controller.
+ */
+
+GLOBAL(void)
+jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+  my_main_ptr mainPtr;
+  int ci;
+  jpeg_component_info *compptr;
+  int data_unit = cinfo->data_unit;
+
+  mainPtr = (my_main_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_main_controller));
+  cinfo->main = (struct jpeg_c_main_controller *) mainPtr;
+  mainPtr->pub.start_pass = start_pass_main;
+
+  /* We don't need to create a buffer in raw-data mode. */
+  if (cinfo->raw_data_in)
+    return;
+
+  /* Create the buffer.  It holds downsampled data, so each component
+   * may be of a different size.
+   */
+  if (need_full_buffer) {
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+    /* Allocate a full-image virtual array for each component */
+    /* Note we pad the bottom to a multiple of the iMCU height */
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      mainPtr->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
+  ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+   compptr->width_in_data_units * data_unit,
+   (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+        (long) compptr->v_samp_factor) * data_unit,
+   (JDIMENSION) (compptr->v_samp_factor * data_unit));
+    }
+#else
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+  } else {
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+    mainPtr->whole_image[0] = NULL; /* flag for no virtual arrays */
+#endif
+    /* Allocate a strip buffer for each component */
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      mainPtr->buffer[ci] = (*cinfo->mem->alloc_sarray)
+  ((j_common_ptr) cinfo, JPOOL_IMAGE,
+   compptr->width_in_data_units * data_unit,
+   (JDIMENSION) (compptr->v_samp_factor * data_unit));
+    }
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcmarker.c b/Utilities/ITK/Utilities/itkjpeg/jcmarker.c
new file mode 100644
index 0000000000000000000000000000000000000000..fc388d579b44f0cb43cfb3cecf58558067713d4a
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcmarker.c
@@ -0,0 +1,678 @@
+/*
+ * jcmarker.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write JPEG datastream markers.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+typedef enum {      /* JPEG marker codes */
+  M_SOF0  = 0xc0,
+  M_SOF1  = 0xc1,
+  M_SOF2  = 0xc2,
+  M_SOF3  = 0xc3,
+  
+  M_SOF5  = 0xc5,
+  M_SOF6  = 0xc6,
+  M_SOF7  = 0xc7,
+  
+  M_JPG   = 0xc8,
+  M_SOF9  = 0xc9,
+  M_SOF10 = 0xca,
+  M_SOF11 = 0xcb,
+  
+  M_SOF13 = 0xcd,
+  M_SOF14 = 0xce,
+  M_SOF15 = 0xcf,
+  
+  M_DHT   = 0xc4,
+  
+  M_DAC   = 0xcc,
+  
+  M_RST0  = 0xd0,
+  M_RST1  = 0xd1,
+  M_RST2  = 0xd2,
+  M_RST3  = 0xd3,
+  M_RST4  = 0xd4,
+  M_RST5  = 0xd5,
+  M_RST6  = 0xd6,
+  M_RST7  = 0xd7,
+  
+  M_SOI   = 0xd8,
+  M_EOI   = 0xd9,
+  M_SOS   = 0xda,
+  M_DQT   = 0xdb,
+  M_DNL   = 0xdc,
+  M_DRI   = 0xdd,
+  M_DHP   = 0xde,
+  M_EXP   = 0xdf,
+  
+  M_APP0  = 0xe0,
+  M_APP1  = 0xe1,
+  M_APP2  = 0xe2,
+  M_APP3  = 0xe3,
+  M_APP4  = 0xe4,
+  M_APP5  = 0xe5,
+  M_APP6  = 0xe6,
+  M_APP7  = 0xe7,
+  M_APP8  = 0xe8,
+  M_APP9  = 0xe9,
+  M_APP10 = 0xea,
+  M_APP11 = 0xeb,
+  M_APP12 = 0xec,
+  M_APP13 = 0xed,
+  M_APP14 = 0xee,
+  M_APP15 = 0xef,
+  
+  M_JPG0  = 0xf0,
+  M_JPG13 = 0xfd,
+  M_COM   = 0xfe,
+  
+  M_TEM   = 0x01,
+  
+  M_ERROR = 0x100
+} JPEG_MARKER;
+
+
+/* Private state */
+
+typedef struct {
+  struct jpeg_marker_writer pub; /* public fields */
+
+  unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */
+} my_marker_writer;
+
+typedef my_marker_writer * my_marker_ptr;
+
+
+/*
+ * Basic output routines.
+ *
+ * Note that we do not support suspension while writing a marker.
+ * Therefore, an application using suspension must ensure that there is
+ * enough buffer space for the initial markers (typ. 600-700 bytes) before
+ * calling jpeg_start_compress, and enough space to write the trailing EOI
+ * (a few bytes) before calling jpeg_finish_compress.  Multipass compression
+ * modes are not supported at all with suspension, so those two are the only
+ * points where markers will be written.
+ */
+
+LOCAL(void)
+emit_byte (j_compress_ptr cinfo, int val)
+/* Emit a byte */
+{
+  struct jpeg_destination_mgr * dest = cinfo->dest;
+
+  *(dest->next_output_byte)++ = (JOCTET) val;
+  if (--dest->free_in_buffer == 0) {
+    if (! (*dest->empty_output_buffer) (cinfo))
+      ERREXIT(cinfo, JERR_CANT_SUSPEND);
+  }
+}
+
+
+LOCAL(void)
+emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark)
+/* Emit a marker code */
+{
+  emit_byte(cinfo, 0xFF);
+  emit_byte(cinfo, (int) mark);
+}
+
+
+LOCAL(void)
+emit_2bytes (j_compress_ptr cinfo, int value)
+/* Emit a 2-byte integer; these are always MSB first in JPEG files */
+{
+  emit_byte(cinfo, (value >> 8) & 0xFF);
+  emit_byte(cinfo, value & 0xFF);
+}
+
+
+/*
+ * Routines to write specific marker types.
+ */
+
+LOCAL(int)
+emit_dqt (j_compress_ptr cinfo, int index)
+/* Emit a DQT marker */
+/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
+{
+  JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index];
+  int prec;
+  int i;
+
+  if (qtbl == NULL)
+    ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index);
+
+  prec = 0;
+  for (i = 0; i < DCTSIZE2; i++) {
+    if (qtbl->quantval[i] > 255)
+      prec = 1;
+  }
+
+  if (! qtbl->sent_table) {
+    emit_marker(cinfo, M_DQT);
+
+    emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
+
+    emit_byte(cinfo, index + (prec<<4));
+
+    for (i = 0; i < DCTSIZE2; i++) {
+      /* The table entries must be emitted in zigzag order. */
+      unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
+      if (prec)
+  emit_byte(cinfo, (int) (qval >> 8));
+      emit_byte(cinfo, (int) (qval & 0xFF));
+    }
+
+    qtbl->sent_table = TRUE;
+  }
+
+  return prec;
+}
+
+
+LOCAL(void)
+emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
+/* Emit a DHT marker */
+{
+  JHUFF_TBL * htbl;
+  int length, i;
+  
+  if (is_ac) {
+    htbl = cinfo->ac_huff_tbl_ptrs[index];
+    index += 0x10;    /* output index has AC bit set */
+  } else {
+    htbl = cinfo->dc_huff_tbl_ptrs[index];
+  }
+
+  if (htbl == NULL)
+    ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
+  
+  if (! htbl->sent_table) {
+    emit_marker(cinfo, M_DHT);
+    
+    length = 0;
+    for (i = 1; i <= 16; i++)
+      length += htbl->bits[i];
+    
+    emit_2bytes(cinfo, length + 2 + 1 + 16);
+    emit_byte(cinfo, index);
+    
+    for (i = 1; i <= 16; i++)
+      emit_byte(cinfo, htbl->bits[i]);
+    
+    for (i = 0; i < length; i++)
+      emit_byte(cinfo, htbl->huffval[i]);
+    
+    htbl->sent_table = TRUE;
+  }
+}
+
+
+LOCAL(void)
+emit_dac (j_compress_ptr cinfo)
+/* Emit a DAC marker */
+/* Since the useful info is so small, we want to emit all the tables in */
+/* one DAC marker.  Therefore this routine does its own scan of the table. */
+{
+#ifdef C_ARITH_CODING_SUPPORTED
+  char dc_in_use[NUM_ARITH_TBLS];
+  char ac_in_use[NUM_ARITH_TBLS];
+  int length, i;
+  jpeg_component_info *compptr;
+  
+  for (i = 0; i < NUM_ARITH_TBLS; i++)
+    dc_in_use[i] = ac_in_use[i] = 0;
+  
+  for (i = 0; i < cinfo->comps_in_scan; i++) {
+    compptr = cinfo->cur_comp_info[i];
+    dc_in_use[compptr->dc_tbl_no] = 1;
+    ac_in_use[compptr->ac_tbl_no] = 1;
+  }
+  
+  length = 0;
+  for (i = 0; i < NUM_ARITH_TBLS; i++)
+    length += dc_in_use[i] + ac_in_use[i];
+  
+  emit_marker(cinfo, M_DAC);
+  
+  emit_2bytes(cinfo, length*2 + 2);
+  
+  for (i = 0; i < NUM_ARITH_TBLS; i++) {
+    if (dc_in_use[i]) {
+      emit_byte(cinfo, i);
+      emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
+    }
+    if (ac_in_use[i]) {
+      emit_byte(cinfo, i + 0x10);
+      emit_byte(cinfo, cinfo->arith_ac_K[i]);
+    }
+  }
+#else
+  (void)cinfo;
+#endif /* C_ARITH_CODING_SUPPORTED */
+}
+
+
+LOCAL(void)
+emit_dri (j_compress_ptr cinfo)
+/* Emit a DRI marker */
+{
+  emit_marker(cinfo, M_DRI);
+  
+  emit_2bytes(cinfo, 4);  /* fixed length */
+
+  emit_2bytes(cinfo, (int) cinfo->restart_interval);
+}
+
+
+LOCAL(void)
+emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
+/* Emit a SOF marker */
+{
+  int ci;
+  jpeg_component_info *compptr;
+  
+  emit_marker(cinfo, code);
+  
+  emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
+
+  /* Make sure image isn't bigger than SOF field can handle */
+  if ((long) cinfo->image_height > 65535L ||
+      (long) cinfo->image_width > 65535L)
+    ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535);
+
+  emit_byte(cinfo, cinfo->data_precision);
+  emit_2bytes(cinfo, (int) cinfo->image_height);
+  emit_2bytes(cinfo, (int) cinfo->image_width);
+
+  emit_byte(cinfo, cinfo->num_components);
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    emit_byte(cinfo, compptr->component_id);
+    emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor);
+    emit_byte(cinfo, compptr->quant_tbl_no);
+  }
+}
+
+
+LOCAL(void)
+emit_sos (j_compress_ptr cinfo)
+/* Emit a SOS marker */
+{
+  int i, td, ta;
+  jpeg_component_info *compptr;
+  
+  emit_marker(cinfo, M_SOS);
+  
+  emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
+  
+  emit_byte(cinfo, cinfo->comps_in_scan);
+  
+  for (i = 0; i < cinfo->comps_in_scan; i++) {
+    compptr = cinfo->cur_comp_info[i];
+    emit_byte(cinfo, compptr->component_id);
+    td = compptr->dc_tbl_no;
+    ta = compptr->ac_tbl_no;
+    if (cinfo->process == JPROC_PROGRESSIVE) {
+      /* Progressive mode: only DC or only AC tables are used in one scan;
+       * furthermore, Huffman coding of DC refinement uses no table at all.
+       * We emit 0 for unused field(s); this is recommended by the P&M text
+       * but does not seem to be specified in the standard.
+       */
+      if (cinfo->Ss == 0) {
+  ta = 0;      /* DC scan */
+  if (cinfo->Ah != 0 && !cinfo->arith_code)
+    td = 0;    /* no DC table either */
+      } else {
+  td = 0;      /* AC scan */
+      }
+    }
+    emit_byte(cinfo, (td << 4) + ta);
+  }
+
+  emit_byte(cinfo, cinfo->Ss);
+  emit_byte(cinfo, cinfo->Se);
+  emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al);
+}
+
+
+LOCAL(void)
+emit_jfif_app0 (j_compress_ptr cinfo)
+/* Emit a JFIF-compliant APP0 marker */
+{
+  /*
+   * Length of APP0 block  (2 bytes)
+   * Block ID      (4 bytes - ASCII "JFIF")
+   * Zero byte      (1 byte to terminate the ID string)
+   * Version Major, Minor  (2 bytes - major first)
+   * Units      (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
+   * Xdpu      (2 bytes - dots per unit horizontal)
+   * Ydpu      (2 bytes - dots per unit vertical)
+   * Thumbnail X size    (1 byte)
+   * Thumbnail Y size    (1 byte)
+   */
+  
+  emit_marker(cinfo, M_APP0);
+  
+  emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
+
+  emit_byte(cinfo, 0x4A);  /* Identifier: ASCII "JFIF" */
+  emit_byte(cinfo, 0x46);
+  emit_byte(cinfo, 0x49);
+  emit_byte(cinfo, 0x46);
+  emit_byte(cinfo, 0);
+  emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */
+  emit_byte(cinfo, cinfo->JFIF_minor_version);
+  emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
+  emit_2bytes(cinfo, (int) cinfo->X_density);
+  emit_2bytes(cinfo, (int) cinfo->Y_density);
+  emit_byte(cinfo, 0);    /* No thumbnail image */
+  emit_byte(cinfo, 0);
+}
+
+
+LOCAL(void)
+emit_adobe_app14 (j_compress_ptr cinfo)
+/* Emit an Adobe APP14 marker */
+{
+  /*
+   * Length of APP14 block  (2 bytes)
+   * Block ID      (5 bytes - ASCII "Adobe")
+   * Version Number    (2 bytes - currently 100)
+   * Flags0      (2 bytes - currently 0)
+   * Flags1      (2 bytes - currently 0)
+   * Color transform    (1 byte)
+   *
+   * Although Adobe TN 5116 mentions Version = 101, all the Adobe files
+   * now in circulation seem to use Version = 100, so that's what we write.
+   *
+   * We write the color transform byte as 1 if the JPEG color space is
+   * YCbCr, 2 if it's YCCK, 0 otherwise.  Adobe's definition has to do with
+   * whether the encoder performed a transformation, which is pretty useless.
+   */
+  
+  emit_marker(cinfo, M_APP14);
+  
+  emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */
+
+  emit_byte(cinfo, 0x41);  /* Identifier: ASCII "Adobe" */
+  emit_byte(cinfo, 0x64);
+  emit_byte(cinfo, 0x6F);
+  emit_byte(cinfo, 0x62);
+  emit_byte(cinfo, 0x65);
+  emit_2bytes(cinfo, 100);  /* Version */
+  emit_2bytes(cinfo, 0);  /* Flags0 */
+  emit_2bytes(cinfo, 0);  /* Flags1 */
+  switch (cinfo->jpeg_color_space) {
+  case JCS_YCbCr:
+    emit_byte(cinfo, 1);  /* Color transform = 1 */
+    break;
+  case JCS_YCCK:
+    emit_byte(cinfo, 2);  /* Color transform = 2 */
+    break;
+  default:
+    emit_byte(cinfo, 0);  /* Color transform = 0 */
+    break;
+  }
+}
+
+
+/*
+ * These routines allow writing an arbitrary marker with parameters.
+ * The only intended use is to emit COM or APPn markers after calling
+ * write_file_header and before calling write_frame_header.
+ * Other uses are not guaranteed to produce desirable results.
+ * Counting the parameter bytes properly is the caller's responsibility.
+ */
+
+METHODDEF(void)
+write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+/* Emit an arbitrary marker header */
+{
+  if (datalen > (unsigned int) 65533)    /* safety check */
+    ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+  emit_marker(cinfo, (JPEG_MARKER) marker);
+
+  emit_2bytes(cinfo, (int) (datalen + 2));  /* total length */
+}
+
+METHODDEF(void)
+write_marker_byte (j_compress_ptr cinfo, int val)
+/* Emit one byte of marker parameters following write_marker_header */
+{
+  emit_byte(cinfo, val);
+}
+
+
+/*
+ * Write datastream header.
+ * This consists of an SOI and optional APPn markers.
+ * We recommend use of the JFIF marker, but not the Adobe marker,
+ * when using YCbCr or grayscale data.  The JFIF marker should NOT
+ * be used for any other JPEG colorspace.  The Adobe marker is helpful
+ * to distinguish RGB, CMYK, and YCCK colorspaces.
+ * Note that an application can write additional header markers after
+ * jpeg_start_compress returns.
+ */
+
+METHODDEF(void)
+write_file_header (j_compress_ptr cinfo)
+{
+  my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+  emit_marker(cinfo, M_SOI);  /* first the SOI */
+
+  /* SOI is defined to reset restart interval to 0 */
+  marker->last_restart_interval = 0;
+
+  if (cinfo->write_JFIF_header)  /* next an optional JFIF APP0 */
+    emit_jfif_app0(cinfo);
+  if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */
+    emit_adobe_app14(cinfo);
+}
+
+
+/*
+ * Write frame header.
+ * This consists of DQT and SOFn markers.
+ * Note that we do not emit the SOF until we have emitted the DQT(s).
+ * This avoids compatibility problems with incorrect implementations that
+ * try to error-check the quant table numbers as soon as they see the SOF.
+ */
+
+METHODDEF(void)
+write_frame_header (j_compress_ptr cinfo)
+{
+  int ci, prec;
+  boolean is_baseline;
+  jpeg_component_info *compptr;
+
+  prec = 0;
+  if (cinfo->process != JPROC_LOSSLESS) {
+    /* Emit DQT for each quantization table.
+     * Note that emit_dqt() suppresses any duplicate tables.
+     */
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      prec += emit_dqt(cinfo, compptr->quant_tbl_no);
+    }
+    /* now prec is nonzero iff there are any 16-bit quant tables. */
+  }
+
+  /* Check for a non-baseline specification.
+   * Note we assume that Huffman table numbers won't be changed later.
+   */
+  if (cinfo->arith_code || cinfo->process != JPROC_SEQUENTIAL ||
+      cinfo->data_precision != 8) {
+    is_baseline = FALSE;
+  } else {
+    is_baseline = TRUE;
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
+  is_baseline = FALSE;
+    }
+    if (prec && is_baseline) {
+      is_baseline = FALSE;
+      /* If it's baseline except for quantizer size, warn the user */
+      TRACEMS(cinfo, 0, JTRC_16BIT_TABLES);
+    }
+  }
+
+  /* Emit the proper SOF marker */
+  if (cinfo->arith_code) {
+    if (cinfo->process == JPROC_PROGRESSIVE)
+      emit_sof(cinfo, M_SOF10); /* SOF code for progressive arithmetic */
+    else if (cinfo->process == JPROC_LOSSLESS)
+      emit_sof(cinfo, M_SOF11);  /* SOF code for lossless arithmetic */
+    else
+      emit_sof(cinfo, M_SOF9);  /* SOF code for sequential arithmetic */
+  } else {
+    if (cinfo->process == JPROC_PROGRESSIVE)
+      emit_sof(cinfo, M_SOF2);  /* SOF code for progressive Huffman */
+    else if (cinfo->process == JPROC_LOSSLESS)
+      emit_sof(cinfo, M_SOF3);  /* SOF code for lossless Huffman */
+    else if (is_baseline)
+      emit_sof(cinfo, M_SOF0);  /* SOF code for baseline implementation */
+    else
+      emit_sof(cinfo, M_SOF1);  /* SOF code for non-baseline Huffman file */
+  }
+}
+
+
+/*
+ * Write scan header.
+ * This consists of DHT or DAC markers, optional DRI, and SOS.
+ * Compressed data will be written following the SOS.
+ */
+
+METHODDEF(void)
+write_scan_header (j_compress_ptr cinfo)
+{
+  my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+  int i;
+  jpeg_component_info *compptr;
+
+  if (cinfo->arith_code) {
+    /* Emit arith conditioning info.  We may have some duplication
+     * if the file has multiple scans, but it's so small it's hardly
+     * worth worrying about.
+     */
+    emit_dac(cinfo);
+  } else {
+    /* Emit Huffman tables.
+     * Note that emit_dht() suppresses any duplicate tables.
+     */
+    for (i = 0; i < cinfo->comps_in_scan; i++) {
+      compptr = cinfo->cur_comp_info[i];
+      if (cinfo->process == JPROC_PROGRESSIVE) {
+  /* Progressive mode: only DC or only AC tables are used in one scan */
+  if (cinfo->Ss == 0) {
+    if (cinfo->Ah == 0)  /* DC needs no table for refinement scan */
+      emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+  } else {
+    emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+  }
+      } else if (cinfo->process == JPROC_LOSSLESS) {
+  /* Lossless mode: only DC tables are used */
+  emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+      } else {
+  /* Sequential mode: need both DC and AC tables */
+  emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+  emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+      }
+    }
+  }
+
+  /* Emit DRI if required --- note that DRI value could change for each scan.
+   * We avoid wasting space with unnecessary DRIs, however.
+   */
+  if (cinfo->restart_interval != marker->last_restart_interval) {
+    emit_dri(cinfo);
+    marker->last_restart_interval = cinfo->restart_interval;
+  }
+
+  emit_sos(cinfo);
+}
+
+
+/*
+ * Write datastream trailer.
+ */
+
+METHODDEF(void)
+write_file_trailer (j_compress_ptr cinfo)
+{
+  emit_marker(cinfo, M_EOI);
+}
+
+
+/*
+ * Write an abbreviated table-specification datastream.
+ * This consists of SOI, DQT and DHT tables, and EOI.
+ * Any table that is defined and not marked sent_table = TRUE will be
+ * emitted.  Note that all tables will be marked sent_table = TRUE at exit.
+ */
+
+METHODDEF(void)
+write_tables_only (j_compress_ptr cinfo)
+{
+  int i;
+
+  emit_marker(cinfo, M_SOI);
+
+  for (i = 0; i < NUM_QUANT_TBLS; i++) {
+    if (cinfo->quant_tbl_ptrs[i] != NULL)
+      (void) emit_dqt(cinfo, i);
+  }
+
+  if (! cinfo->arith_code) {
+    for (i = 0; i < NUM_HUFF_TBLS; i++) {
+      if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
+  emit_dht(cinfo, i, FALSE);
+      if (cinfo->ac_huff_tbl_ptrs[i] != NULL)
+  emit_dht(cinfo, i, TRUE);
+    }
+  }
+
+  emit_marker(cinfo, M_EOI);
+}
+
+
+/*
+ * Initialize the marker writer module.
+ */
+
+GLOBAL(void)
+jinit_marker_writer (j_compress_ptr cinfo)
+{
+  my_marker_ptr marker;
+
+  /* Create the subobject */
+  marker = (my_marker_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_marker_writer));
+  cinfo->marker = (struct jpeg_marker_writer *) marker;
+  /* Initialize method pointers */
+  marker->pub.write_file_header = write_file_header;
+  marker->pub.write_frame_header = write_frame_header;
+  marker->pub.write_scan_header = write_scan_header;
+  marker->pub.write_file_trailer = write_file_trailer;
+  marker->pub.write_tables_only = write_tables_only;
+  marker->pub.write_marker_header = write_marker_header;
+  marker->pub.write_marker_byte = write_marker_byte;
+  /* Initialize private state */
+  marker->last_restart_interval = 0;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcmaster.c b/Utilities/ITK/Utilities/itkjpeg/jcmaster.c
new file mode 100644
index 0000000000000000000000000000000000000000..c9851268b7a6bc540edff46af9b9b8ad5c2a2c0e
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcmaster.c
@@ -0,0 +1,648 @@
+/*
+ * jcmaster.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains master control logic for the JPEG compressor.
+ * These routines are concerned with parameter validation, initial setup,
+ * and inter-pass control (determining the number of passes and the work 
+ * to be done in each pass).
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"    /* Private declarations for lossy codec */
+
+
+/* Private state */
+
+typedef enum {
+  main_pass,    /* input data, also do first output step */
+  huff_opt_pass,    /* Huffman code optimization pass */
+  output_pass    /* data output pass */
+} c_pass_type;
+
+typedef struct {
+  struct jpeg_comp_master pub;  /* public fields */
+
+  c_pass_type pass_type;  /* the type of the current pass */
+
+  int pass_number;    /* # of passes completed */
+  int total_passes;    /* total # of passes needed */
+
+  int scan_number;    /* current index in scan_info[] */
+} my_comp_master;
+
+typedef my_comp_master * my_master_ptr;
+
+
+/*
+ * Support routines that do various essential calculations.
+ */
+
+LOCAL(void)
+initial_setup (j_compress_ptr cinfo)
+/* Do computations that are needed before master selection phase */
+{
+  int ci;
+  jpeg_component_info *compptr;
+  long samplesperrow;
+  JDIMENSION jd_samplesperrow;
+  int data_unit = cinfo->data_unit;
+
+  /* Sanity check on image dimensions */
+  if (cinfo->image_height <= 0 || cinfo->image_width <= 0
+      || cinfo->num_components <= 0 || cinfo->input_components <= 0)
+    ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
+  /* Make sure image isn't bigger than I can handle */
+  if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
+      (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
+    ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+
+  /* Width of an input scanline must be representable as JDIMENSION. */
+  samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
+  jd_samplesperrow = (JDIMENSION) samplesperrow;
+  if ((long) jd_samplesperrow != samplesperrow)
+    ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+  /* For now, precision must match compiled-in value... */
+  if (cinfo->data_precision != BITS_IN_JSAMPLE)
+    ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
+
+  /* Check that number of components won't exceed internal array sizes */
+  if (cinfo->num_components > MAX_COMPONENTS)
+    ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+       MAX_COMPONENTS);
+
+  /* Compute maximum sampling factors; check factor validity */
+  cinfo->max_h_samp_factor = 1;
+  cinfo->max_v_samp_factor = 1;
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
+  compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+      ERREXIT(cinfo, JERR_BAD_SAMPLING);
+    cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
+           compptr->h_samp_factor);
+    cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
+           compptr->v_samp_factor);
+  }
+
+  /* Compute dimensions of components */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Fill in the correct component_index value; don't rely on application */
+    compptr->component_index = ci;
+    /* For compression, we never do any codec-based processing. */
+    compptr->codec_data_unit = data_unit;
+    /* Size in data units */
+    compptr->width_in_data_units = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+        (long) (cinfo->max_h_samp_factor * data_unit));
+    compptr->height_in_data_units = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+        (long) (cinfo->max_v_samp_factor * data_unit));
+    /* Size in samples */
+    compptr->downsampled_width = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+        (long) cinfo->max_h_samp_factor);
+    compptr->downsampled_height = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+        (long) cinfo->max_v_samp_factor);
+    /* Mark component needed (this flag isn't actually used for compression) */
+    compptr->component_needed = TRUE;
+  }
+
+  /* Compute number of fully interleaved MCU rows (number of times that
+   * main controller will call coefficient controller).
+   */
+  cinfo->total_iMCU_rows = (JDIMENSION)
+    jdiv_round_up((long) cinfo->image_height,
+      (long) (cinfo->max_v_samp_factor*data_unit));
+}
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+#define NEED_SCAN_SCRIPT
+#else
+#ifdef C_LOSSLESS_SUPPORTED
+#define NEED_SCAN_SCRIPT
+#endif
+#endif
+
+#ifdef NEED_SCAN_SCRIPT
+
+LOCAL(void)
+validate_script (j_compress_ptr cinfo)
+/* Verify that the scan script in cinfo->scan_info[] is valid; also
+ * determine whether it uses progressive JPEG, and set cinfo->process.
+ */
+{
+  const jpeg_scan_info * scanptr;
+  int scanno, ncomps, ci, coefi, thisi;
+  int Ss, Se, Ah, Al;
+  boolean component_sent[MAX_COMPONENTS];
+#ifdef C_PROGRESSIVE_SUPPORTED
+  int * last_bitpos_ptr;
+  int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
+  /* -1 until that coefficient has been seen; then last Al for it */
+#endif
+
+  if (cinfo->num_scans <= 0)
+    ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
+
+#ifndef C_MULTISCAN_FILES_SUPPORTED
+  if (cinfo->num_scans > 1)
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+
+  scanptr = cinfo->scan_info;
+  if (cinfo->lossless) {
+#ifdef C_LOSSLESS_SUPPORTED
+    cinfo->process = JPROC_LOSSLESS;
+    for (ci = 0; ci < cinfo->num_components; ci++) 
+      component_sent[ci] = FALSE;
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+  }
+  /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
+   * for progressive JPEG, no scan can have this.
+   */
+  else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+    cinfo->process = JPROC_PROGRESSIVE;
+    last_bitpos_ptr = & last_bitpos[0][0];
+    for (ci = 0; ci < cinfo->num_components; ci++) 
+      for (coefi = 0; coefi < DCTSIZE2; coefi++)
+  *last_bitpos_ptr++ = -1;
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+  } else {
+    cinfo->process = JPROC_SEQUENTIAL;
+    for (ci = 0; ci < cinfo->num_components; ci++) 
+      component_sent[ci] = FALSE;
+  }
+
+  for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) {
+    /* Validate component indexes */
+    ncomps = scanptr->comps_in_scan;
+    if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN)
+      ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
+    for (ci = 0; ci < ncomps; ci++) {
+      thisi = scanptr->component_index[ci];
+      if (thisi < 0 || thisi >= cinfo->num_components)
+  ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+      /* Components must appear in SOF order within each scan */
+      if (ci > 0 && thisi <= scanptr->component_index[ci-1])
+  ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+    }
+    /* Validate progression parameters */
+    Ss = scanptr->Ss;
+    Se = scanptr->Se;
+    Ah = scanptr->Ah;
+    Al = scanptr->Al;
+    if (cinfo->process == JPROC_LOSSLESS) {
+#ifdef C_LOSSLESS_SUPPORTED
+      /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that
+       * seems wrong: the upper bound ought to depend on data precision.
+       * Perhaps they really meant 0..N-1 for N-bit precision, which is what
+       * we allow here.
+       */
+      if (Ss < 1 || Ss > 7 ||      /* predictor selector */
+    Se != 0 || Ah != 0 ||
+    Al < 0 || Al >= cinfo->data_precision) /* point transform */
+  ERREXIT1(cinfo, JERR_BAD_LOSSLESS_SCRIPT, scanno);
+      /* Make sure components are not sent twice */
+      for (ci = 0; ci < ncomps; ci++) {
+  thisi = scanptr->component_index[ci];
+  if (component_sent[thisi])
+    ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+  component_sent[thisi] = TRUE;
+      }
+#endif
+    } else if (cinfo->process == JPROC_PROGRESSIVE) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+      /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
+       * seems wrong: the upper bound ought to depend on data precision.
+       * Perhaps they really meant 0..N+1 for N-bit precision.
+       * Here we allow 0..10 for 8-bit data; Al larger than 10 results in
+       * out-of-range reconstructed DC values during the first DC scan,
+       * which might cause problems for some decoders.
+       */
+#if BITS_IN_JSAMPLE == 8
+#define MAX_AH_AL 10
+#else
+#define MAX_AH_AL 13
+#endif
+      if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
+    Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
+  ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+      if (Ss == 0) {
+  if (Se != 0)    /* DC and AC together not OK */
+    ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+      } else {
+  if (ncomps != 1)  /* AC scans must be for only one component */
+    ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+      }
+      for (ci = 0; ci < ncomps; ci++) {
+  last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
+  if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
+    ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+  for (coefi = Ss; coefi <= Se; coefi++) {
+    if (last_bitpos_ptr[coefi] < 0) {
+      /* first scan of this coefficient */
+      if (Ah != 0)
+        ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+    } else {
+      /* not first scan */
+      if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
+        ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+    }
+    last_bitpos_ptr[coefi] = Al;
+  }
+      }
+#endif
+    } else {
+      /* For sequential JPEG, all progression parameters must be these: */
+      if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
+  ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+      /* Make sure components are not sent twice */
+      for (ci = 0; ci < ncomps; ci++) {
+  thisi = scanptr->component_index[ci];
+  if (component_sent[thisi])
+    ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+  component_sent[thisi] = TRUE;
+      }
+    }
+  }
+
+  /* Now verify that everything got sent. */
+  if (cinfo->process == JPROC_PROGRESSIVE) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+    /* For progressive mode, we only check that at least some DC data
+     * got sent for each component; the spec does not require that all bits
+     * of all coefficients be transmitted.  Would it be wiser to enforce
+     * transmission of all coefficient bits??
+     */
+    for (ci = 0; ci < cinfo->num_components; ci++) {
+      if (last_bitpos[ci][0] < 0)
+  ERREXIT(cinfo, JERR_MISSING_DATA);
+    }
+#endif
+  } else {
+    for (ci = 0; ci < cinfo->num_components; ci++) {
+      if (! component_sent[ci])
+  ERREXIT(cinfo, JERR_MISSING_DATA);
+    }
+  }
+}
+
+#endif /* NEED_SCAN_SCRIPT */
+
+
+LOCAL(void)
+select_scan_parameters (j_compress_ptr cinfo)
+/* Set up the scan parameters for the current scan */
+{
+  int ci;
+
+#ifdef NEED_SCAN_SCRIPT
+  if (cinfo->scan_info != NULL) {
+    /* Prepare for current scan --- the script is already validated */
+    my_master_ptr master = (my_master_ptr) cinfo->master;
+    const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number;
+
+    cinfo->comps_in_scan = scanptr->comps_in_scan;
+    for (ci = 0; ci < scanptr->comps_in_scan; ci++) {
+      cinfo->cur_comp_info[ci] =
+  &cinfo->comp_info[scanptr->component_index[ci]];
+    }
+    cinfo->Ss = scanptr->Ss;
+    cinfo->Se = scanptr->Se;
+    cinfo->Ah = scanptr->Ah;
+    cinfo->Al = scanptr->Al;
+  } else
+#endif
+  {
+    /* Prepare for single sequential-JPEG scan containing all components */
+    if (cinfo->num_components > MAX_COMPS_IN_SCAN)
+      ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+         MAX_COMPS_IN_SCAN);
+    cinfo->comps_in_scan = cinfo->num_components;
+    for (ci = 0; ci < cinfo->num_components; ci++) {
+      cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
+    }
+    if (cinfo->lossless) {
+#ifdef C_LOSSLESS_SUPPORTED
+    /* If we fall through to here, the user specified lossless, but did not
+     * provide a scan script.
+     */
+      ERREXIT(cinfo, JERR_NO_LOSSLESS_SCRIPT);
+#endif
+    } else {
+      cinfo->process = JPROC_SEQUENTIAL;
+      cinfo->Ss = 0;
+      cinfo->Se = DCTSIZE2-1;
+      cinfo->Ah = 0;
+      cinfo->Al = 0;
+    }
+  }
+}
+
+
+LOCAL(void)
+per_scan_setup (j_compress_ptr cinfo)
+/* Do computations that are needed before processing a JPEG scan */
+/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
+{
+  int ci, mcublks, tmp;
+  jpeg_component_info *compptr;
+  int data_unit = cinfo->data_unit;
+  
+  if (cinfo->comps_in_scan == 1) {
+    
+    /* Noninterleaved (single-component) scan */
+    compptr = cinfo->cur_comp_info[0];
+    
+    /* Overall image size in MCUs */
+    cinfo->MCUs_per_row = compptr->width_in_data_units;
+    cinfo->MCU_rows_in_scan = compptr->height_in_data_units;
+    
+    /* For noninterleaved scan, always one block per MCU */
+    compptr->MCU_width = 1;
+    compptr->MCU_height = 1;
+    compptr->MCU_data_units = 1;
+    compptr->MCU_sample_width = data_unit;
+    compptr->last_col_width = 1;
+    /* For noninterleaved scans, it is convenient to define last_row_height
+     * as the number of block rows present in the last iMCU row.
+     */
+    tmp = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+    if (tmp == 0) tmp = compptr->v_samp_factor;
+    compptr->last_row_height = tmp;
+    
+    /* Prepare array describing MCU composition */
+    cinfo->data_units_in_MCU = 1;
+    cinfo->MCU_membership[0] = 0;
+    
+  } else {
+    
+    /* Interleaved (multi-component) scan */
+    if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
+      ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
+         MAX_COMPS_IN_SCAN);
+    
+    /* Overall image size in MCUs */
+    cinfo->MCUs_per_row = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_width,
+        (long) (cinfo->max_h_samp_factor*data_unit));
+    cinfo->MCU_rows_in_scan = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_height,
+        (long) (cinfo->max_v_samp_factor*data_unit));
+    
+    cinfo->data_units_in_MCU = 0;
+    
+    for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+      compptr = cinfo->cur_comp_info[ci];
+      /* Sampling factors give # of blocks of component in each MCU */
+      compptr->MCU_width = compptr->h_samp_factor;
+      compptr->MCU_height = compptr->v_samp_factor;
+      compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height;
+      compptr->MCU_sample_width = compptr->MCU_width * data_unit;
+      /* Figure number of non-dummy blocks in last MCU column & row */
+      tmp = (int) (compptr->width_in_data_units % compptr->MCU_width);
+      if (tmp == 0) tmp = compptr->MCU_width;
+      compptr->last_col_width = tmp;
+      tmp = (int) (compptr->height_in_data_units % compptr->MCU_height);
+      if (tmp == 0) tmp = compptr->MCU_height;
+      compptr->last_row_height = tmp;
+      /* Prepare array describing MCU composition */
+      mcublks = compptr->MCU_data_units;
+      if (cinfo->data_units_in_MCU + mcublks > C_MAX_DATA_UNITS_IN_MCU)
+  ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
+      while (mcublks-- > 0) {
+  cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci;
+      }
+    }
+    
+  }
+
+  /* Convert restart specified in rows to actual MCU count. */
+  /* Note that count must fit in 16 bits, so we provide limiting. */
+  if (cinfo->restart_in_rows > 0) {
+    long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
+    cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
+  }
+}
+
+
+/*
+ * Per-pass setup.
+ * This is called at the beginning of each pass.  We determine which modules
+ * will be active during this pass and give them appropriate start_pass calls.
+ * We also set is_last_pass to indicate whether any more passes will be
+ * required.
+ */
+
+METHODDEF(void)
+prepare_for_pass (j_compress_ptr cinfo)
+{
+  /* j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec; */
+  my_master_ptr master = (my_master_ptr) cinfo->master;
+
+  switch (master->pass_type) {
+  case main_pass:
+    /* Initial pass: will collect input data, and do either Huffman
+     * optimization or data output for the first scan.
+     */
+    select_scan_parameters(cinfo);
+    per_scan_setup(cinfo);
+    if (! cinfo->raw_data_in) {
+      (*cinfo->cconvert->start_pass) (cinfo);
+      (*cinfo->downsample->start_pass) (cinfo);
+      (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
+    }
+    (*cinfo->codec->entropy_start_pass) (cinfo, cinfo->optimize_coding);
+    (*cinfo->codec->start_pass) (cinfo,
+         (master->total_passes > 1 ?
+          JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
+    (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
+    if (cinfo->optimize_coding) {
+      /* No immediate data output; postpone writing frame/scan headers */
+      master->pub.call_pass_startup = FALSE;
+    } else {
+      /* Will write frame/scan headers at first jpeg_write_scanlines call */
+      master->pub.call_pass_startup = TRUE;
+    }
+    break;
+#ifdef ENTROPY_OPT_SUPPORTED
+  case huff_opt_pass:
+    /* Do Huffman optimization for a scan after the first one. */
+    select_scan_parameters(cinfo);
+    per_scan_setup(cinfo);
+    if ((*cinfo->codec->need_optimization_pass) (cinfo)) {
+      (*cinfo->codec->entropy_start_pass) (cinfo, TRUE);
+      (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST);
+      master->pub.call_pass_startup = FALSE;
+      break;
+    }
+    /* Special case: Huffman DC refinement scans need no Huffman table
+     * and therefore we can skip the optimization pass for them.
+     */
+    master->pass_type = output_pass;
+    master->pass_number++;
+    /*FALLTHROUGH*/
+#endif
+  case output_pass:
+    /* Do a data-output pass. */
+    /* We need not repeat per-scan setup if prior optimization pass did it. */
+    if (! cinfo->optimize_coding) {
+      select_scan_parameters(cinfo);
+      per_scan_setup(cinfo);
+    }
+    (*cinfo->codec->entropy_start_pass) (cinfo, FALSE);
+    (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST);
+    /* We emit frame/scan headers now */
+    if (master->scan_number == 0)
+      (*cinfo->marker->write_frame_header) (cinfo);
+    (*cinfo->marker->write_scan_header) (cinfo);
+    master->pub.call_pass_startup = FALSE;
+    break;
+  default:
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+  }
+
+  master->pub.is_last_pass = (master->pass_number == master->total_passes-1);
+
+  /* Set up progress monitor's pass info if present */
+  if (cinfo->progress != NULL) {
+    cinfo->progress->completed_passes = master->pass_number;
+    cinfo->progress->total_passes = master->total_passes;
+  }
+}
+
+
+/*
+ * Special start-of-pass hook.
+ * This is called by jpeg_write_scanlines if call_pass_startup is TRUE.
+ * In single-pass processing, we need this hook because we don't want to
+ * write frame/scan headers during jpeg_start_compress; we want to let the
+ * application write COM markers etc. between jpeg_start_compress and the
+ * jpeg_write_scanlines loop.
+ * In multi-pass processing, this routine is not used.
+ */
+
+METHODDEF(void)
+pass_startup (j_compress_ptr cinfo)
+{
+  cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
+
+  (*cinfo->marker->write_frame_header) (cinfo);
+  (*cinfo->marker->write_scan_header) (cinfo);
+}
+
+
+/*
+ * Finish up at end of pass.
+ */
+
+METHODDEF(void)
+finish_pass_master (j_compress_ptr cinfo)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  my_master_ptr master = (my_master_ptr) cinfo->master;
+
+  /* The entropy coder always needs an end-of-pass call,
+   * either to analyze statistics or to flush its output buffer.
+   */
+  (*lossyc->pub.entropy_finish_pass) (cinfo);
+
+  /* Update state for next pass */
+  switch (master->pass_type) {
+  case main_pass:
+    /* next pass is either output of scan 0 (after optimization)
+     * or output of scan 1 (if no optimization).
+     */
+    master->pass_type = output_pass;
+    if (! cinfo->optimize_coding)
+      master->scan_number++;
+    break;
+  case huff_opt_pass:
+    /* next pass is always output of current scan */
+    master->pass_type = output_pass;
+    break;
+  case output_pass:
+    /* next pass is either optimization or output of next scan */
+    if (cinfo->optimize_coding)
+      master->pass_type = huff_opt_pass;
+    master->scan_number++;
+    break;
+  }
+
+  master->pass_number++;
+}
+
+
+/*
+ * Initialize master compression control.
+ */
+
+GLOBAL(void)
+jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
+{
+  my_master_ptr master;
+
+  master = (my_master_ptr)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          SIZEOF(my_comp_master));
+  cinfo->master = (struct jpeg_comp_master *) master;
+  master->pub.prepare_for_pass = prepare_for_pass;
+  master->pub.pass_startup = pass_startup;
+  master->pub.finish_pass = finish_pass_master;
+  master->pub.is_last_pass = FALSE;
+
+  cinfo->data_unit = cinfo->lossless ? 1 : DCTSIZE;
+
+  /* Validate parameters, determine derived values */
+  initial_setup(cinfo);
+
+  if (cinfo->scan_info != NULL) {
+#ifdef NEED_SCAN_SCRIPT
+    validate_script(cinfo);
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+  } else {
+    cinfo->process = JPROC_SEQUENTIAL;
+    cinfo->num_scans = 1;
+  }
+
+  if ((cinfo->arith_code == 0) &&
+      (cinfo->process == JPROC_PROGRESSIVE ||  /*  TEMPORARY HACK ??? */
+       cinfo->process == JPROC_LOSSLESS))
+    cinfo->optimize_coding = TRUE; /* assume default tables no good for
+            * progressive mode or lossless mode */
+
+  /* Initialize my private state */
+  if (transcode_only) {
+    /* no main pass in transcoding */
+    if (cinfo->optimize_coding)
+      master->pass_type = huff_opt_pass;
+    else
+      master->pass_type = output_pass;
+  } else {
+    /* for normal compression, first pass is always this type: */
+    master->pass_type = main_pass;
+  }
+  master->scan_number = 0;
+  master->pass_number = 0;
+  if (cinfo->optimize_coding)
+    master->total_passes = cinfo->num_scans * 2;
+  else
+    master->total_passes = cinfo->num_scans;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcodec.c b/Utilities/ITK/Utilities/itkjpeg/jcodec.c
new file mode 100644
index 0000000000000000000000000000000000000000..9529caaa1bfc183c8f0fd25b7d1b6ad91704a586
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcodec.c
@@ -0,0 +1,53 @@
+/*
+ * jcodec.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains utility functions for the JPEG codec(s).
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"
+#include "jlossls.h"
+
+
+/*
+ * Initialize the compression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void)
+jinit_c_codec (j_compress_ptr cinfo)
+{
+  if (cinfo->process == JPROC_LOSSLESS) {
+#ifdef C_LOSSLESS_SUPPORTED
+    jinit_lossless_c_codec(cinfo);
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+  } else
+    jinit_lossy_c_codec(cinfo);
+}
+
+
+/*
+ * Initialize the decompression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void)
+jinit_d_codec (j_decompress_ptr cinfo)
+{
+  if (cinfo->process == JPROC_LOSSLESS) {
+#ifdef D_LOSSLESS_SUPPORTED
+    jinit_lossless_d_codec(cinfo);
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+  } else
+    jinit_lossy_d_codec(cinfo);
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcomapi.c b/Utilities/ITK/Utilities/itkjpeg/jcomapi.c
new file mode 100644
index 0000000000000000000000000000000000000000..2d45449a855f97303af981b8cb3f3e24cf93ad46
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcomapi.c
@@ -0,0 +1,106 @@
+/*
+ * jcomapi.c
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface routines that are used for both
+ * compression and decompression.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Abort processing of a JPEG compression or decompression operation,
+ * but don't destroy the object itself.
+ *
+ * For this, we merely clean up all the nonpermanent memory pools.
+ * Note that temp files (virtual arrays) are not allowed to belong to
+ * the permanent pool, so we will be able to close all temp files here.
+ * Closing a data source or destination, if necessary, is the application's
+ * responsibility.
+ */
+
+GLOBAL(void)
+jpeg_abort (j_common_ptr cinfo)
+{
+  int pool;
+
+  /* Do nothing if called on a not-initialized or destroyed JPEG object. */
+  if (cinfo->mem == NULL)
+    return;
+
+  /* Releasing pools in reverse order might help avoid fragmentation
+   * with some (brain-damaged) malloc libraries.
+   */
+  for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
+    (*cinfo->mem->free_pool) (cinfo, pool);
+  }
+
+  /* Reset overall state for possible reuse of object */
+  if (cinfo->is_decompressor) {
+    cinfo->global_state = DSTATE_START;
+    /* Try to keep application from accessing now-deleted marker list.
+     * A bit kludgy to do it here, but this is the most central place.
+     */
+    ((j_decompress_ptr) cinfo)->marker_list = NULL;
+  } else {
+    cinfo->global_state = CSTATE_START;
+  }
+}
+
+
+/*
+ * Destruction of a JPEG object.
+ *
+ * Everything gets deallocated except the master jpeg_compress_struct itself
+ * and the error manager struct.  Both of these are supplied by the application
+ * and must be freed, if necessary, by the application.  (Often they are on
+ * the stack and so don't need to be freed anyway.)
+ * Closing a data source or destination, if necessary, is the application's
+ * responsibility.
+ */
+
+GLOBAL(void)
+jpeg_destroy (j_common_ptr cinfo)
+{
+  /* We need only tell the memory manager to release everything. */
+  /* NB: mem pointer is NULL if memory mgr failed to initialize. */
+  if (cinfo->mem != NULL)
+    (*cinfo->mem->self_destruct) (cinfo);
+  cinfo->mem = NULL;    /* be safe if jpeg_destroy is called twice */
+  cinfo->global_state = 0;  /* mark it destroyed */
+}
+
+
+/*
+ * Convenience routines for allocating quantization and Huffman tables.
+ * (Would jutils.c be a more reasonable place to put these?)
+ */
+
+GLOBAL(JQUANT_TBL *)
+jpeg_alloc_quant_table (j_common_ptr cinfo)
+{
+  JQUANT_TBL *tbl;
+
+  tbl = (JQUANT_TBL *)
+    (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL));
+  tbl->sent_table = FALSE;  /* make sure this is false in any new table */
+  return tbl;
+}
+
+
+GLOBAL(JHUFF_TBL *)
+jpeg_alloc_huff_table (j_common_ptr cinfo)
+{
+  JHUFF_TBL *tbl;
+
+  tbl = (JHUFF_TBL *)
+    (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL));
+  tbl->sent_table = FALSE;  /* make sure this is false in any new table */
+  return tbl;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jconfig.doc b/Utilities/ITK/Utilities/itkjpeg/jconfig.doc
new file mode 100644
index 0000000000000000000000000000000000000000..c18d1c064b77287209ab5d5d6b83e591b702df9f
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jconfig.doc
@@ -0,0 +1,155 @@
+/*
+ * jconfig.doc
+ *
+ * Copyright (C) 1991-1994, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file documents the configuration options that are required to
+ * customize the JPEG software for a particular system.
+ *
+ * The actual configuration options for a particular installation are stored
+ * in jconfig.h.  On many machines, jconfig.h can be generated automatically
+ * or copied from one of the "canned" jconfig files that we supply.  But if
+ * you need to generate a jconfig.h file by hand, this file tells you how.
+ *
+ * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING.
+ * EDIT A COPY NAMED JCONFIG.H.
+ */
+
+
+/*
+ * These symbols indicate the properties of your machine or compiler.
+ * #define the symbol if yes, #undef it if no.
+ */
+
+/* Does your compiler support function prototypes?
+ * (If not, you also need to use ansi2knr, see install.doc)
+ */
+#define HAVE_PROTOTYPES
+
+/* Does your compiler support the declaration "unsigned char" ?
+ * How about "unsigned short" ?
+ */
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
+
+/* Define "void" as "char" if your compiler doesn't know about type void.
+ * NOTE: be sure to define void such that "void *" represents the most general
+ * pointer type, e.g., that returned by malloc().
+ */
+/* #define void char */
+
+/* Define "const" as empty if your compiler doesn't know the "const" keyword.
+ */
+/* #define const */
+
+/* Define this if an ordinary "char" type is unsigned.
+ * If you're not sure, leaving it undefined will work at some cost in speed.
+ * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
+ */
+#undef CHAR_IS_UNSIGNED
+
+/* Define this if your system has an ANSI-conforming <stddef.h> file.
+ */
+#define HAVE_STDDEF_H
+
+/* Define this if your system has an ANSI-conforming <stdlib.h> file.
+ */
+#define HAVE_STDLIB_H
+
+/* Define this if your system does not have an ANSI/SysV <string.h>,
+ * but does have a BSD-style <strings.h>.
+ */
+#undef NEED_BSD_STRINGS
+
+/* Define this if your system does not provide typedef size_t in any of the
+ * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
+ * <sys/types.h> instead.
+ */
+#undef NEED_SYS_TYPES_H
+
+/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
+ * unless you are using a large-data memory model or 80386 flat-memory mode.
+ * On less brain-damaged CPUs this symbol must not be defined.
+ * (Defining this symbol causes large data structures to be referenced through
+ * "far" pointers and to be allocated with a special version of malloc.)
+ */
+#undef NEED_FAR_POINTERS
+
+/* Define this if your linker needs global names to be unique in less
+ * than the first 15 characters.
+ */
+#undef NEED_SHORT_EXTERNAL_NAMES
+
+/* Although a real ANSI C compiler can deal perfectly well with pointers to
+ * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
+ * and pseudo-ANSI compilers get confused.  To keep one of these bozos happy,
+ * define INCOMPLETE_TYPES_BROKEN.  This is not recommended unless you
+ * actually get "missing structure definition" warnings or errors while
+ * compiling the JPEG code.
+ */
+#undef INCOMPLETE_TYPES_BROKEN
+
+
+/*
+ * The following options affect code selection within the JPEG library,
+ * but they don't need to be visible to applications using the library.
+ * To minimize application namespace pollution, the symbols won't be
+ * defined unless JPEG_INTERNALS has been defined.
+ */
+
+#ifdef JPEG_INTERNALS
+
+/* Define this if your compiler implements ">>" on signed values as a logical
+ * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
+ * which is the normal and rational definition.
+ */
+#undef RIGHT_SHIFT_IS_UNSIGNED
+
+
+#endif /* JPEG_INTERNALS */
+
+
+/*
+ * The remaining options do not affect the JPEG library proper,
+ * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c).
+ * Other applications can ignore these.
+ */
+
+#ifdef JPEG_CJPEG_DJPEG
+
+/* These defines indicate which image (non-JPEG) file formats are allowed. */
+
+#define BMP_SUPPORTED		/* BMP image file format */
+#define GIF_SUPPORTED		/* GIF image file format */
+#define PPM_SUPPORTED		/* PBMPLUS PPM/PGM image file format */
+#undef RLE_SUPPORTED		/* Utah RLE image file format */
+#define TARGA_SUPPORTED		/* Targa image file format */
+
+/* Define this if you want to name both input and output files on the command
+ * line, rather than using stdout and optionally stdin.  You MUST do this if
+ * your system can't cope with binary I/O to stdin/stdout.  See comments at
+ * head of cjpeg.c or djpeg.c.
+ */
+#undef TWO_FILE_COMMANDLINE
+
+/* Define this if your system needs explicit cleanup of temporary files.
+ * This is crucial under MS-DOS, where the temporary "files" may be areas
+ * of extended memory; on most other systems it's not as important.
+ */
+#undef NEED_SIGNAL_CATCHER
+
+/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
+ * This is necessary on systems that distinguish text files from binary files,
+ * and is harmless on most systems that don't.  If you have one of the rare
+ * systems that complains about the "b" spec, define this symbol.
+ */
+#undef DONT_USE_B_MODE
+
+/* Define this if you want percent-done progress reports from cjpeg/djpeg.
+ */
+#undef PROGRESS_REPORT
+
+
+#endif /* JPEG_CJPEG_DJPEG */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jconfig.h.in b/Utilities/ITK/Utilities/itkjpeg/jconfig.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..66aaa74bf482db8902e87840310fa53b8bb0baca
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jconfig.h.in
@@ -0,0 +1,69 @@
+/* jconfig.h --- source file edited by configure script */
+/* see jconfig.doc for explanations */
+
+#define HAVE_PROTOTYPES
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
+#undef void
+#undef const
+#undef CHAR_IS_UNSIGNED
+#ifndef HAVE_STDDEF_H
+#define HAVE_STDDEF_H
+#endif
+#ifndef HAVE_STDLIB_H
+#define HAVE_STDLIB_H
+#endif
+#undef NEED_BSD_STRINGS
+#undef NEED_SYS_TYPES_H
+#undef NEED_FAR_POINTERS
+#undef NEED_SHORT_EXTERNAL_NAMES
+/* Define this if you get warnings about undefined structures. */
+#undef INCOMPLETE_TYPES_BROKEN
+
+
+#if defined(_WIN32) && !(defined(__CYGWIN__) || defined(__MINGW32__))
+/* Define "boolean" as unsigned char, not int, per Windows custom */
+/* don't conflict if rpcndr.h already read; Note that the w32api headers
+   used by Cygwin and Mingw do not define "boolean", so jmorecfg.h
+   handles it later. */
+#ifndef __RPCNDR_H__
+typedef unsigned char boolean;
+#endif
+#define HAVE_BOOLEAN            /* prevent jmorecfg.h from redefining it */
+#endif
+
+#ifdef JPEG_INTERNALS
+
+#undef RIGHT_SHIFT_IS_UNSIGNED
+#define INLINE
+/* These are for configuring the JPEG memory manager. */
+#undef DEFAULT_MAX_MEM
+#undef NO_MKTEMP
+
+#endif /* JPEG_INTERNALS */
+
+#ifdef JPEG_CJPEG_DJPEG
+
+#define BMP_SUPPORTED           /* BMP image file format */
+#define GIF_SUPPORTED           /* GIF image file format */
+#define PPM_SUPPORTED           /* PBMPLUS PPM/PGM image file format */
+#undef RLE_SUPPORTED            /* Utah RLE image file format */
+#define TARGA_SUPPORTED         /* Targa image file format */
+
+#undef TWO_FILE_COMMANDLINE
+#undef NEED_SIGNAL_CATCHER
+#undef DONT_USE_B_MODE
+
+/* Define this if you want percent-done progress reports from cjpeg/djpeg. */
+#undef PROGRESS_REPORT
+
+#endif /* JPEG_CJPEG_DJPEG */
+
+
+/* names mangling */
+
+#include "@BITS_TYPE_JPEG_MANGLE_NAME@"
+
+#if defined(__BORLANDC__)
+#pragma warn -8004 /* Disable "foo is assigned a value that is never used." */
+#endif
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcparam.c b/Utilities/ITK/Utilities/itkjpeg/jcparam.c
new file mode 100644
index 0000000000000000000000000000000000000000..1f3d0022eaacf1e41d1dc9f094233c5282c46a20
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcparam.c
@@ -0,0 +1,687 @@
+/*
+ * jcparam.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains optional default-setting code for the JPEG compressor.
+ * Applications do not have to use this file, but those that don't use it
+ * must know a lot more about the innards of the JPEG code.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Quantization table setup routines
+ */
+
+GLOBAL(void)
+jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
+          const unsigned int *basic_table,
+          int scale_factor, boolean force_baseline)
+/* Define a quantization table equal to the basic_table times
+ * a scale factor (given as a percentage).
+ * If force_baseline is TRUE, the computed quantization table entries
+ * are limited to 1..255 for JPEG baseline compatibility.
+ */
+{
+  JQUANT_TBL ** qtblptr;
+  int i;
+  long temp;
+
+  /* Safety check to ensure start_compress not called yet. */
+  if (cinfo->global_state != CSTATE_START)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS)
+    ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl);
+
+  qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
+
+  if (*qtblptr == NULL)
+    *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+
+  for (i = 0; i < DCTSIZE2; i++) {
+    temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
+    /* limit the values to the valid range */
+    if (temp <= 0L) temp = 1L;
+    if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
+    if (force_baseline && temp > 255L)
+      temp = 255L;    /* limit to baseline range if requested */
+    (*qtblptr)->quantval[i] = (UINT16) temp;
+  }
+
+  /* Initialize sent_table FALSE so table will be written to JPEG file. */
+  (*qtblptr)->sent_table = FALSE;
+}
+
+
+GLOBAL(void)
+jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
+       boolean force_baseline)
+/* Set or change the 'quality' (quantization) setting, using default tables
+ * and a straight percentage-scaling quality scale.  In most cases it's better
+ * to use jpeg_set_quality (below); this entry point is provided for
+ * applications that insist on a linear percentage scaling.
+ */
+{
+  /* These are the sample quantization tables given in JPEG spec section K.1.
+   * The spec says that the values given produce "good" quality, and
+   * when divided by 2, "very good" quality.
+   */
+  static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {
+    16,  11,  10,  16,  24,  40,  51,  61,
+    12,  12,  14,  19,  26,  58,  60,  55,
+    14,  13,  16,  24,  40,  57,  69,  56,
+    14,  17,  22,  29,  51,  87,  80,  62,
+    18,  22,  37,  56,  68, 109, 103,  77,
+    24,  35,  55,  64,  81, 104, 113,  92,
+    49,  64,  78,  87, 103, 121, 120, 101,
+    72,  92,  95,  98, 112, 100, 103,  99
+  };
+  static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
+    17,  18,  24,  47,  99,  99,  99,  99,
+    18,  21,  26,  66,  99,  99,  99,  99,
+    24,  26,  56,  99,  99,  99,  99,  99,
+    47,  66,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99,
+    99,  99,  99,  99,  99,  99,  99,  99
+  };
+
+  /* Set up two quantization tables using the specified scaling */
+  jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
+           scale_factor, force_baseline);
+  jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
+           scale_factor, force_baseline);
+}
+
+
+GLOBAL(int)
+jpeg_quality_scaling (int quality)
+/* Convert a user-specified quality rating to a percentage scaling factor
+ * for an underlying quantization table, using our recommended scaling curve.
+ * The input 'quality' factor should be 0 (terrible) to 100 (very good).
+ */
+{
+  /* Safety limit on quality factor.  Convert 0 to 1 to avoid zero divide. */
+  if (quality <= 0) quality = 1;
+  if (quality > 100) quality = 100;
+
+  /* The basic table is used as-is (scaling 100) for a quality of 50.
+   * Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
+   * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table
+   * to make all the table entries 1 (hence, minimum quantization loss).
+   * Qualities 1..50 are converted to scaling percentage 5000/Q.
+   */
+  if (quality < 50)
+    quality = 5000 / quality;
+  else
+    quality = 200 - quality*2;
+
+  return quality;
+}
+
+
+GLOBAL(void)
+jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
+/* Set or change the 'quality' (quantization) setting, using default tables.
+ * This is the standard quality-adjusting entry point for typical user
+ * interfaces; only those who want detailed control over quantization tables
+ * would use the preceding three routines directly.
+ */
+{
+  /* Convert user 0-100 rating to percentage scaling */
+  quality = jpeg_quality_scaling(quality);
+
+  /* Set up standard quality tables */
+  jpeg_set_linear_quality(cinfo, quality, force_baseline);
+}
+
+
+/*
+ * Huffman table setup routines
+ */
+
+LOCAL(void)
+add_huff_table (j_compress_ptr cinfo,
+    JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
+/* Define a Huffman table */
+{
+  int nsymbols, len;
+
+  if (*htblptr == NULL)
+    *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+
+  /* Copy the number-of-symbols-of-each-code-length counts */
+  MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
+
+  /* Validate the counts.  We do this here mainly so we can copy the right
+   * number of symbols from the val[] array, without risking marching off
+   * the end of memory.  jchuff.c will do a more thorough test later.
+   */
+  nsymbols = 0;
+  for (len = 1; len <= 16; len++)
+    nsymbols += bits[len];
+  if (nsymbols < 1 || nsymbols > 256)
+    ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+
+  MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8));
+
+  /* Initialize sent_table FALSE so table will be written to JPEG file. */
+  (*htblptr)->sent_table = FALSE;
+}
+
+
+LOCAL(void)
+std_huff_tables (j_compress_ptr cinfo)
+/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
+/* IMPORTANT: these are only valid for 8-bit data precision! */
+{
+  static const UINT8 bits_dc_luminance[17] =
+    { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+  static const UINT8 val_dc_luminance[] =
+    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+  
+  static const UINT8 bits_dc_chrominance[17] =
+    { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+  static const UINT8 val_dc_chrominance[] =
+    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+  
+  static const UINT8 bits_ac_luminance[17] =
+    { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+  static const UINT8 val_ac_luminance[] =
+    { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+      0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+      0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+      0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+      0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+      0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+      0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+      0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+      0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+      0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+      0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+      0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+      0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+      0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+      0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+      0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+      0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+      0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+      0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+      0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+      0xf9, 0xfa };
+  
+  static const UINT8 bits_ac_chrominance[17] =
+    { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+  static const UINT8 val_ac_chrominance[] =
+    { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+      0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+      0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+      0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+      0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+      0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+      0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+      0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+      0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+      0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+      0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+      0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+      0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+      0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+      0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+      0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+      0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+      0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+      0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+      0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+      0xf9, 0xfa };
+  
+  add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
+     bits_dc_luminance, val_dc_luminance);
+  add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
+     bits_ac_luminance, val_ac_luminance);
+  add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
+     bits_dc_chrominance, val_dc_chrominance);
+  add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
+     bits_ac_chrominance, val_ac_chrominance);
+}
+
+
+/*
+ * Default parameter setup for compression.
+ *
+ * Applications that don't choose to use this routine must do their
+ * own setup of all these parameters.  Alternately, you can call this
+ * to establish defaults and then alter parameters selectively.  This
+ * is the recommended approach since, if we add any new parameters,
+ * your code will still work (they'll be set to reasonable defaults).
+ */
+
+GLOBAL(void)
+jpeg_set_defaults (j_compress_ptr cinfo)
+{
+  int i;
+
+  /* Safety check to ensure start_compress not called yet. */
+  if (cinfo->global_state != CSTATE_START)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  /* Allocate comp_info array large enough for maximum component count.
+   * Array is made permanent in case application wants to compress
+   * multiple images at same param settings.
+   */
+  if (cinfo->comp_info == NULL)
+    cinfo->comp_info = (jpeg_component_info *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+          MAX_COMPONENTS * SIZEOF(jpeg_component_info));
+
+  /* Initialize everything not dependent on the color space */
+
+  cinfo->lossless = FALSE;
+  cinfo->data_precision = BITS_IN_JSAMPLE;
+  /* Set up two quantization tables using default quality of 75 */
+  jpeg_set_quality(cinfo, 75, TRUE);
+  /* Set up two Huffman tables */
+  std_huff_tables(cinfo);
+
+  /* Initialize default arithmetic coding conditioning */
+  for (i = 0; i < NUM_ARITH_TBLS; i++) {
+    cinfo->arith_dc_L[i] = 0;
+    cinfo->arith_dc_U[i] = 1;
+    cinfo->arith_ac_K[i] = 5;
+  }
+
+  /* Default is no multiple-scan output */
+  cinfo->scan_info = NULL;
+  cinfo->num_scans = 0;
+
+  /* Expect normal source image, not raw downsampled data */
+  cinfo->raw_data_in = FALSE;
+
+  /* Use Huffman coding, not arithmetic coding, by default */
+  cinfo->arith_code = FALSE;
+
+  /* By default, don't do extra passes to optimize entropy coding */
+  cinfo->optimize_coding = FALSE;
+  /* The standard Huffman tables are only valid for 8-bit data precision.
+   * If the precision is higher, force optimization on so that usable
+   * tables will be computed.  This test can be removed if default tables
+   * are supplied that are valid for the desired precision.
+   */
+  if (cinfo->data_precision > 8)
+    cinfo->optimize_coding = TRUE;
+
+  /* By default, use the simpler non-cosited sampling alignment */
+  cinfo->CCIR601_sampling = FALSE;
+
+  /* No input smoothing */
+  cinfo->smoothing_factor = 0;
+
+  /* DCT algorithm preference */
+  cinfo->dct_method = JDCT_DEFAULT;
+
+  /* No restart markers */
+  cinfo->restart_interval = 0;
+  cinfo->restart_in_rows = 0;
+
+  /* Fill in default JFIF marker parameters.  Note that whether the marker
+   * will actually be written is determined by jpeg_set_colorspace.
+   *
+   * By default, the library emits JFIF version code 1.01.
+   * An application that wants to emit JFIF 1.02 extension markers should set
+   * JFIF_minor_version to 2.  We could probably get away with just defaulting
+   * to 1.02, but there may still be some decoders in use that will complain
+   * about that; saying 1.01 should minimize compatibility problems.
+   */
+  cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */
+  cinfo->JFIF_minor_version = 1;
+  cinfo->density_unit = 0;  /* Pixel size is unknown by default */
+  cinfo->X_density = 1;    /* Pixel aspect ratio is square by default */
+  cinfo->Y_density = 1;
+
+  /* Choose JPEG colorspace based on input space, set defaults accordingly */
+
+  jpeg_default_colorspace(cinfo);
+}
+
+
+/*
+ * Select an appropriate JPEG colorspace for in_color_space.
+ */
+
+GLOBAL(void)
+jpeg_default_colorspace (j_compress_ptr cinfo)
+{
+  if (cinfo->lossless)
+    jpeg_set_colorspace(cinfo, cinfo->in_color_space);
+  else { /* lossy */
+    switch (cinfo->in_color_space) {
+    case JCS_GRAYSCALE:
+      jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
+      break;
+    case JCS_RGB:
+      jpeg_set_colorspace(cinfo, JCS_YCbCr);
+      break;
+    case JCS_YCbCr:
+      jpeg_set_colorspace(cinfo, JCS_YCbCr);
+      break;
+    case JCS_CMYK:
+      jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */
+      break;
+    case JCS_YCCK:
+      jpeg_set_colorspace(cinfo, JCS_YCCK);
+      break;
+    case JCS_UNKNOWN:
+      jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
+      break;
+    default:
+      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+    }
+  }
+}
+
+
+/*
+ * Set the JPEG colorspace, and choose colorspace-dependent default values.
+ */
+
+GLOBAL(void)
+jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
+{
+  jpeg_component_info * compptr;
+  int ci;
+
+#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl)  \
+  (compptr = &cinfo->comp_info[index], \
+   compptr->component_id = (id), \
+   compptr->h_samp_factor = (hsamp), \
+   compptr->v_samp_factor = (vsamp), \
+   compptr->quant_tbl_no = (quant), \
+   compptr->dc_tbl_no = (dctbl), \
+   compptr->ac_tbl_no = (actbl) )
+
+  /* Safety check to ensure start_compress not called yet. */
+  if (cinfo->global_state != CSTATE_START)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  /* For all colorspaces, we use Q and Huff tables 0 for luminance components,
+   * tables 1 for chrominance components.
+   */
+
+  cinfo->jpeg_color_space = colorspace;
+
+  cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */
+  cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */
+
+  switch (colorspace) {
+  case JCS_GRAYSCALE:
+    cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
+    cinfo->num_components = 1;
+    /* JFIF specifies component ID 1 */
+    SET_COMP(0, 1, 1,1, 0, 0,0);
+    break;
+  case JCS_RGB:
+    cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
+    cinfo->num_components = 3;
+    SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0);
+    SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0);
+    SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0);
+    break;
+  case JCS_YCbCr:
+    cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
+    cinfo->num_components = 3;
+    /* JFIF specifies component IDs 1,2,3 */
+    if (cinfo->lossless) {
+      SET_COMP(0, 1, 1,1, 0, 0,0);
+      SET_COMP(1, 2, 1,1, 1, 1,1);
+      SET_COMP(2, 3, 1,1, 1, 1,1);
+    } else { /* lossy */
+      /* We default to 2x2 subsamples of chrominance */
+      SET_COMP(0, 1, 2,2, 0, 0,0);
+      SET_COMP(1, 2, 1,1, 1, 1,1);
+      SET_COMP(2, 3, 1,1, 1, 1,1);
+    }
+    break;
+  case JCS_CMYK:
+    cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
+    cinfo->num_components = 4;
+    SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0);
+    SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0);
+    SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0);
+    SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0);
+    break;
+  case JCS_YCCK:
+    cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
+    cinfo->num_components = 4;
+    if (cinfo->lossless) {
+      SET_COMP(0, 1, 1,1, 0, 0,0);
+      SET_COMP(1, 2, 1,1, 1, 1,1);
+      SET_COMP(2, 3, 1,1, 1, 1,1);
+      SET_COMP(3, 4, 1,1, 0, 0,0);
+    } else { /* lossy */
+      SET_COMP(0, 1, 2,2, 0, 0,0);
+      SET_COMP(1, 2, 1,1, 1, 1,1);
+      SET_COMP(2, 3, 1,1, 1, 1,1);
+      SET_COMP(3, 4, 2,2, 0, 0,0);
+    }
+    break;
+  case JCS_UNKNOWN:
+    cinfo->num_components = cinfo->input_components;
+    if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS)
+      ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+         MAX_COMPONENTS);
+    for (ci = 0; ci < cinfo->num_components; ci++) {
+      SET_COMP(ci, ci, 1,1, 0, 0,0);
+    }
+    break;
+  default:
+    ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+  }
+}
+
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+
+LOCAL(jpeg_scan_info *)
+fill_scans (jpeg_scan_info * scanptr, int ncomps,
+      int Ss, int Se, int Ah, int Al)
+/* Support routine: generate one scan for each component */
+{
+  int ci;
+
+  for (ci = 0; ci < ncomps; ci++) {
+    scanptr->comps_in_scan = 1;
+    scanptr->component_index[0] = ci;
+    scanptr->Ss = Ss;
+    scanptr->Se = Se;
+    scanptr->Ah = Ah;
+    scanptr->Al = Al;
+    scanptr++;
+  }
+  return scanptr;
+}
+
+
+LOCAL(jpeg_scan_info *)
+fill_a_scan (jpeg_scan_info * scanptr, int ci,
+       int Ss, int Se, int Ah, int Al)
+/* Support routine: generate one scan for specified component */
+{
+  scanptr->comps_in_scan = 1;
+  scanptr->component_index[0] = ci;
+  scanptr->Ss = Ss;
+  scanptr->Se = Se;
+  scanptr->Ah = Ah;
+  scanptr->Al = Al;
+  scanptr++;
+  return scanptr;
+}
+
+LOCAL(jpeg_scan_info *)
+fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al)
+/* Support routine: generate interleaved DC scan if possible, else N scans */
+{
+  int ci;
+
+  if (ncomps <= MAX_COMPS_IN_SCAN) {
+    /* Single interleaved DC scan */
+    scanptr->comps_in_scan = ncomps;
+    for (ci = 0; ci < ncomps; ci++)
+      scanptr->component_index[ci] = ci;
+    scanptr->Ss = scanptr->Se = 0;
+    scanptr->Ah = Ah;
+    scanptr->Al = Al;
+    scanptr++;
+  } else {
+    /* Noninterleaved DC scan for each component */
+    scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al);
+  }
+  return scanptr;
+}
+
+
+/*
+ * Create a recommended progressive-JPEG script.
+ * cinfo->num_components and cinfo->jpeg_color_space must be correct.
+ */
+
+GLOBAL(void)
+jpeg_simple_progression (j_compress_ptr cinfo)
+{
+  int ncomps = cinfo->num_components;
+  int nscans;
+  jpeg_scan_info * scanptr;
+
+  /* Safety check to ensure start_compress not called yet. */
+  if (cinfo->global_state != CSTATE_START)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  /* Figure space needed for script.  Calculation must match code below! */
+  if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
+    /* Custom script for YCbCr color images. */
+    nscans = 10;
+  } else {
+    /* All-purpose script for other color spaces. */
+    if (ncomps > MAX_COMPS_IN_SCAN)
+      nscans = 6 * ncomps;  /* 2 DC + 4 AC scans per component */
+    else
+      nscans = 2 + 4 * ncomps;  /* 2 DC scans; 4 AC scans per component */
+  }
+
+  /* Allocate space for script.
+   * We need to put it in the permanent pool in case the application performs
+   * multiple compressions without changing the settings.  To avoid a memory
+   * leak if jpeg_simple_progression is called repeatedly for the same JPEG
+   * object, we try to re-use previously allocated space, and we allocate
+   * enough space to handle YCbCr even if initially asked for grayscale.
+   */
+  if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
+    cinfo->script_space_size = MAX(nscans, 10);
+    cinfo->script_space = (jpeg_scan_info *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+      cinfo->script_space_size * SIZEOF(jpeg_scan_info));
+  }
+  scanptr = cinfo->script_space;
+  cinfo->scan_info = scanptr;
+  cinfo->num_scans = nscans;
+
+  if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
+    /* Custom script for YCbCr color images. */
+    /* Initial DC scan */
+    scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
+    /* Initial AC scan: get some luma data out in a hurry */
+    scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2);
+    /* Chroma data is too small to be worth expending many scans on */
+    scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1);
+    scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1);
+    /* Complete spectral selection for luma AC */
+    scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2);
+    /* Refine next bit of luma AC */
+    scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1);
+    /* Finish DC successive approximation */
+    scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
+    /* Finish AC successive approximation */
+    scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0);
+    scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0);
+    /* Luma bottom bit comes last since it's usually largest scan */
+    scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
+  } else {
+    /* All-purpose script for other color spaces. */
+    /* Successive approximation first pass */
+    scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
+    scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2);
+    scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2);
+    /* Successive approximation second pass */
+    scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1);
+    /* Successive approximation final pass */
+    scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
+    scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0);
+  }
+}
+
+#endif /* C_PROGRESSIVE_SUPPORTED */
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+/*
+ * Create a single-entry lossless-JPEG script containing all components.
+ * cinfo->num_components must be correct.
+ */
+
+GLOBAL(void)
+jpeg_simple_lossless (j_compress_ptr cinfo, int predictor, int point_transform)
+{
+  int ncomps = cinfo->num_components;
+  int nscans = 1;
+  int ci;
+  jpeg_scan_info * scanptr;
+
+  /* Safety check to ensure start_compress not called yet. */
+  if (cinfo->global_state != CSTATE_START)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  cinfo->lossless = TRUE;
+
+  /* Set jpeg_color_space. */
+  jpeg_default_colorspace(cinfo);
+
+  /* Check to ensure that all components will fit in one scan. */
+  if (cinfo->num_components > MAX_COMPS_IN_SCAN)
+    ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+       MAX_COMPS_IN_SCAN);
+
+  /* Allocate space for script.
+   * We need to put it in the permanent pool in case the application performs
+   * multiple compressions without changing the settings.  To avoid a memory
+   * leak if jpeg_simple_lossless is called repeatedly for the same JPEG
+   * object, we try to re-use previously allocated space.
+   */
+  if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
+    cinfo->script_space_size = nscans;
+    cinfo->script_space = (jpeg_scan_info *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+      cinfo->script_space_size * SIZEOF(jpeg_scan_info));
+  }
+  scanptr = cinfo->script_space;
+  cinfo->scan_info = scanptr;
+  cinfo->num_scans = nscans;
+
+  /* Fill the script. */
+  scanptr->comps_in_scan = ncomps;
+  for (ci = 0; ci < ncomps; ci++)
+    scanptr->component_index[ci] = ci;
+  scanptr->Ss = predictor;
+  scanptr->Se = 0;
+  scanptr->Ah = 0;
+  scanptr->Al = point_transform;
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcphuff.c b/Utilities/ITK/Utilities/itkjpeg/jcphuff.c
new file mode 100644
index 0000000000000000000000000000000000000000..63b9e461e3dbf2b468879e3192ae7604c5ee3ff7
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcphuff.c
@@ -0,0 +1,848 @@
+/*
+ * jcphuff.c
+ *
+ * Copyright (C) 1995-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy encoding routines for progressive JPEG.
+ *
+ * We do not support output suspension in this module, since the library
+ * currently does not allow multiple-scan files to be written with output
+ * suspension.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"    /* Private declarations for lossy codec */
+#include "jchuff.h"    /* Declarations shared with jc*huff.c */
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+
+/* Expanded entropy encoder object for progressive Huffman encoding. */
+
+typedef struct {
+  /* Mode flag: TRUE for optimization, FALSE for actual data output */
+  boolean gather_statistics;
+
+  /* Bit-level coding status.
+   * next_output_byte/free_in_buffer are local copies of cinfo->dest fields.
+   */
+  JOCTET * next_output_byte;  /* => next byte to write in buffer */
+  size_t free_in_buffer;  /* # of byte spaces remaining in buffer */
+  INT32 put_buffer;    /* current bit-accumulation buffer */
+  int put_bits;      /* # of bits now in it */
+  j_compress_ptr cinfo;    /* link to cinfo (needed for dump_buffer) */
+
+  /* Coding status for DC components */
+  int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+
+  /* Coding status for AC components */
+  int ac_tbl_no;    /* the table number of the single component */
+  unsigned int EOBRUN;    /* run length of EOBs */
+  unsigned int BE;    /* # of buffered correction bits before MCU */
+  char * bit_buffer;    /* buffer for correction bits (1 per char) */
+  /* packing correction bits tightly would save some space but cost time... */
+
+  unsigned int restarts_to_go;  /* MCUs left in this restart interval */
+  int next_restart_num;    /* next restart number to write (0-7) */
+
+  /* Pointers to derived tables (these workspaces have image lifespan).
+   * Since any one scan codes only DC or only AC, we only need one set
+   * of tables, not one for DC and one for AC.
+   */
+  c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+  /* Statistics tables for optimization; again, one set is enough */
+  long * count_ptrs[NUM_HUFF_TBLS];
+} phuff_entropy_encoder;
+
+typedef phuff_entropy_encoder * phuff_entropy_ptr;
+
+/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit
+ * buffer can hold.  Larger sizes may slightly improve compression, but
+ * 1000 is already well into the realm of overkill.
+ * The minimum safe size is 64 bits.
+ */
+
+#define MAX_CORR_BITS  1000  /* Max # of correction bits I can buffer */
+
+/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
+ * We assume that int right shift is unsigned if INT32 right shift is,
+ * which should be safe.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define ISHIFT_TEMPS  int ishift_temp;
+#define IRIGHT_SHIFT(x,shft)  \
+  ((ishift_temp = (x)) < 0 ? \
+   (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
+   (ishift_temp >> (shft)))
+#else
+#define ISHIFT_TEMPS
+#define IRIGHT_SHIFT(x,shft)  ((x) >> (shft))
+#endif
+
+/* Forward declarations */
+METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo,
+              JBLOCKROW *MCU_data));
+METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo,
+              JBLOCKROW *MCU_data));
+METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo,
+               JBLOCKROW *MCU_data));
+METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo,
+               JBLOCKROW *MCU_data));
+METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo));
+METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo));
+
+
+/*
+ * Initialize for a Huffman-compressed scan using progressive JPEG.
+ */
+
+METHODDEF(void)
+start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
+{  
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+  boolean is_DC_band;
+  int ci, tbl;
+  jpeg_component_info * compptr;
+
+  entropy->cinfo = cinfo;
+  entropy->gather_statistics = gather_statistics;
+
+  is_DC_band = (cinfo->Ss == 0);
+
+  /* We assume jcmaster.c already validated the scan parameters. */
+
+  /* Select execution routines */
+  if (cinfo->Ah == 0) {
+    if (is_DC_band)
+      lossyc->entropy_encode_mcu = encode_mcu_DC_first;
+    else
+      lossyc->entropy_encode_mcu = encode_mcu_AC_first;
+  } else {
+    if (is_DC_band)
+      lossyc->entropy_encode_mcu = encode_mcu_DC_refine;
+    else {
+      lossyc->entropy_encode_mcu = encode_mcu_AC_refine;
+      /* AC refinement needs a correction bit buffer */
+      if (entropy->bit_buffer == NULL)
+  entropy->bit_buffer = (char *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+              MAX_CORR_BITS * SIZEOF(char));
+    }
+  }
+  if (gather_statistics)
+    lossyc->pub.entropy_finish_pass = finish_pass_gather_phuff;
+  else
+    lossyc->pub.entropy_finish_pass = finish_pass_phuff;
+
+  /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1
+   * for AC coefficients.
+   */
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    /* Initialize DC predictions to 0 */
+    entropy->last_dc_val[ci] = 0;
+    /* Get table index */
+    if (is_DC_band) {
+      if (cinfo->Ah != 0)  /* DC refinement needs no table */
+  continue;
+      tbl = compptr->dc_tbl_no;
+    } else {
+      entropy->ac_tbl_no = tbl = compptr->ac_tbl_no;
+    }
+    if (gather_statistics) {
+      /* Check for invalid table index */
+      /* (make_c_derived_tbl does this in the other path) */
+      if (tbl < 0 || tbl >= NUM_HUFF_TBLS)
+        ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl);
+      /* Allocate and zero the statistics tables */
+      /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
+      if (entropy->count_ptrs[tbl] == NULL)
+  entropy->count_ptrs[tbl] = (long *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+              257 * SIZEOF(long));
+      MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long));
+    } else {
+      /* Compute derived values for Huffman table */
+      /* We may do this more than once for a table, but it's not expensive */
+      jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl,
+            & entropy->derived_tbls[tbl]);
+    }
+  }
+
+  /* Initialize AC stuff */
+  entropy->EOBRUN = 0;
+  entropy->BE = 0;
+
+  /* Initialize bit buffer to empty */
+  entropy->put_buffer = 0;
+  entropy->put_bits = 0;
+
+  /* Initialize restart stuff */
+  entropy->restarts_to_go = cinfo->restart_interval;
+  entropy->next_restart_num = 0;
+}
+
+
+/* Outputting bytes to the file.
+ * NB: these must be called only when actually outputting,
+ * that is, entropy->gather_statistics == FALSE.
+ */
+
+/* Emit a byte */
+#define emit_byte(entropy,val)  \
+  { *(entropy)->next_output_byte++ = (JOCTET) (val);  \
+    if (--(entropy)->free_in_buffer == 0)  \
+      dump_buffer(entropy); }
+
+
+LOCAL(void)
+dump_buffer (phuff_entropy_ptr entropy)
+/* Empty the output buffer; we do not support suspension in this module. */
+{
+  struct jpeg_destination_mgr * dest = entropy->cinfo->dest;
+
+  if (! (*dest->empty_output_buffer) (entropy->cinfo))
+    ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
+  /* After a successful buffer dump, must reset buffer pointers */
+  entropy->next_output_byte = dest->next_output_byte;
+  entropy->free_in_buffer = dest->free_in_buffer;
+}
+
+
+/* Outputting bits to the file */
+
+/* Only the right 24 bits of put_buffer are used; the valid bits are
+ * left-justified in this part.  At most 16 bits can be passed to emit_bits
+ * in one call, and we never retain more than 7 bits in put_buffer
+ * between calls, so 24 bits are sufficient.
+ */
+
+INLINE
+LOCAL(void)
+emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
+/* Emit some bits, unless we are in gather mode */
+{
+  /* This routine is heavily used, so it's worth coding tightly. */
+  register INT32 put_buffer = (INT32) code;
+  register int put_bits = entropy->put_bits;
+
+  /* if size is 0, caller used an invalid Huffman table entry */
+  if (size == 0)
+    ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
+
+  if (entropy->gather_statistics)
+    return;      /* do nothing if we're only getting stats */
+
+  put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+  
+  put_bits += size;    /* new number of bits in buffer */
+  
+  put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+  put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */
+
+  while (put_bits >= 8) {
+    int c = (int) ((put_buffer >> 16) & 0xFF);
+    
+    emit_byte(entropy, c);
+    if (c == 0xFF) {    /* need to stuff a zero byte? */
+      emit_byte(entropy, 0);
+    }
+    put_buffer <<= 8;
+    put_bits -= 8;
+  }
+
+  entropy->put_buffer = put_buffer; /* update variables */
+  entropy->put_bits = put_bits;
+}
+
+
+LOCAL(void)
+flush_bits (phuff_entropy_ptr entropy)
+{
+  emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */
+  entropy->put_buffer = 0;     /* and reset bit-buffer to empty */
+  entropy->put_bits = 0;
+}
+
+
+/*
+ * Emit (or just count) a Huffman symbol.
+ */
+
+INLINE
+LOCAL(void)
+emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
+{
+  if (entropy->gather_statistics)
+    entropy->count_ptrs[tbl_no][symbol]++;
+  else {
+    c_derived_tbl * tbl = entropy->derived_tbls[tbl_no];
+    emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]);
+  }
+}
+
+
+/*
+ * Emit bits from a correction bit buffer.
+ */
+
+LOCAL(void)
+emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart,
+        unsigned int nbits)
+{
+  if (entropy->gather_statistics)
+    return;      /* no real work */
+
+  while (nbits > 0) {
+    emit_bits(entropy, (unsigned int) (*bufstart), 1);
+    bufstart++;
+    nbits--;
+  }
+}
+
+
+/*
+ * Emit any pending EOBRUN symbol.
+ */
+
+LOCAL(void)
+emit_eobrun (phuff_entropy_ptr entropy)
+{
+  register int temp, nbits;
+
+  if (entropy->EOBRUN > 0) {  /* if there is any pending EOBRUN */
+    temp = entropy->EOBRUN;
+    nbits = 0;
+    while ((temp >>= 1))
+      nbits++;
+    /* safety check: shouldn't happen given limited correction-bit buffer */
+    if (nbits > 14)
+      ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
+
+    emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4);
+    if (nbits)
+      emit_bits(entropy, entropy->EOBRUN, nbits);
+
+    entropy->EOBRUN = 0;
+
+    /* Emit any buffered correction bits */
+    emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE);
+    entropy->BE = 0;
+  }
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL(void)
+emit_restart (phuff_entropy_ptr entropy, int restart_num)
+{
+  int ci;
+
+  emit_eobrun(entropy);
+
+  if (! entropy->gather_statistics) {
+    flush_bits(entropy);
+    emit_byte(entropy, 0xFF);
+    emit_byte(entropy, JPEG_RST0 + restart_num);
+  }
+
+  if (entropy->cinfo->Ss == 0) {
+    /* Re-initialize DC predictions to 0 */
+    for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++)
+      entropy->last_dc_val[ci] = 0;
+  } else {
+    /* Re-initialize all AC-related fields to 0 */
+    entropy->EOBRUN = 0;
+    entropy->BE = 0;
+  }
+}
+
+
+/*
+ * MCU encoding for DC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+  register int temp, temp2;
+  register int nbits;
+  int blkn, ci;
+  int Al = cinfo->Al;
+  JBLOCKROW block;
+  jpeg_component_info * compptr;
+  ISHIFT_TEMPS
+
+  entropy->next_output_byte = cinfo->dest->next_output_byte;
+  entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+  /* Emit restart marker if needed */
+  if (cinfo->restart_interval)
+    if (entropy->restarts_to_go == 0)
+      emit_restart(entropy, entropy->next_restart_num);
+
+  /* Encode the MCU data blocks */
+  for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+    block = MCU_data[blkn];
+    ci = cinfo->MCU_membership[blkn];
+    compptr = cinfo->cur_comp_info[ci];
+
+    /* Compute the DC value after the required point transform by Al.
+     * This is simply an arithmetic right shift.
+     */
+    temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al);
+
+    /* DC differences are figured on the point-transformed values. */
+    temp = temp2 - entropy->last_dc_val[ci];
+    entropy->last_dc_val[ci] = temp2;
+
+    /* Encode the DC coefficient difference per section G.1.2.1 */
+    temp2 = temp;
+    if (temp < 0) {
+      temp = -temp;    /* temp is abs value of input */
+      /* For a negative input, want temp2 = bitwise complement of abs(input) */
+      /* This code assumes we are on a two's complement machine */
+      temp2--;
+    }
+    
+    /* Find the number of bits needed for the magnitude of the coefficient */
+    nbits = 0;
+    while (temp) {
+      nbits++;
+      temp >>= 1;
+    }
+    /* Check for out-of-range coefficient values.
+     * Since we're encoding a difference, the range limit is twice as much.
+     */
+    if (nbits > MAX_COEF_BITS+1)
+      ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+    
+    /* Count/emit the Huffman-coded symbol for the number of bits */
+    emit_symbol(entropy, compptr->dc_tbl_no, nbits);
+    
+    /* Emit that number of bits of the value, if positive, */
+    /* or the complement of its magnitude, if negative. */
+    if (nbits)      /* emit_bits rejects calls with size 0 */
+      emit_bits(entropy, (unsigned int) temp2, nbits);
+  }
+
+  cinfo->dest->next_output_byte = entropy->next_output_byte;
+  cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+  /* Update restart-interval state too */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0) {
+      entropy->restarts_to_go = cinfo->restart_interval;
+      entropy->next_restart_num++;
+      entropy->next_restart_num &= 7;
+    }
+    entropy->restarts_to_go--;
+  }
+
+  return TRUE;
+}
+
+
+/*
+ * MCU encoding for AC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+  register int temp, temp2;
+  register int nbits;
+  register int r, k;
+  int Se = cinfo->Se;
+  int Al = cinfo->Al;
+  JBLOCKROW block;
+
+  entropy->next_output_byte = cinfo->dest->next_output_byte;
+  entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+  /* Emit restart marker if needed */
+  if (cinfo->restart_interval)
+    if (entropy->restarts_to_go == 0)
+      emit_restart(entropy, entropy->next_restart_num);
+
+  /* Encode the MCU data block */
+  block = MCU_data[0];
+
+  /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
+  
+  r = 0;      /* r = run length of zeros */
+   
+  for (k = cinfo->Ss; k <= Se; k++) {
+    if ((temp = (*block)[jpeg_natural_order[k]]) == 0) {
+      r++;
+      continue;
+    }
+    /* We must apply the point transform by Al.  For AC coefficients this
+     * is an integer division with rounding towards 0.  To do this portably
+     * in C, we shift after obtaining the absolute value; so the code is
+     * interwoven with finding the abs value (temp) and output bits (temp2).
+     */
+    if (temp < 0) {
+      temp = -temp;    /* temp is abs value of input */
+      temp >>= Al;    /* apply the point transform */
+      /* For a negative coef, want temp2 = bitwise complement of abs(coef) */
+      temp2 = ~temp;
+    } else {
+      temp >>= Al;    /* apply the point transform */
+      temp2 = temp;
+    }
+    /* Watch out for case that nonzero coef is zero after point transform */
+    if (temp == 0) {
+      r++;
+      continue;
+    }
+
+    /* Emit any pending EOBRUN */
+    if (entropy->EOBRUN > 0)
+      emit_eobrun(entropy);
+    /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+    while (r > 15) {
+      emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
+      r -= 16;
+    }
+
+    /* Find the number of bits needed for the magnitude of the coefficient */
+    nbits = 1;      /* there must be at least one 1 bit */
+    while ((temp >>= 1))
+      nbits++;
+    /* Check for out-of-range coefficient values */
+    if (nbits > MAX_COEF_BITS)
+      ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+    /* Count/emit Huffman symbol for run length / number of bits */
+    emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits);
+
+    /* Emit that number of bits of the value, if positive, */
+    /* or the complement of its magnitude, if negative. */
+    emit_bits(entropy, (unsigned int) temp2, nbits);
+
+    r = 0;      /* reset zero run length */
+  }
+
+  if (r > 0) {      /* If there are trailing zeroes, */
+    entropy->EOBRUN++;    /* count an EOB */
+    if (entropy->EOBRUN == 0x7FFF)
+      emit_eobrun(entropy);  /* force it out to avoid overflow */
+  }
+
+  cinfo->dest->next_output_byte = entropy->next_output_byte;
+  cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+  /* Update restart-interval state too */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0) {
+      entropy->restarts_to_go = cinfo->restart_interval;
+      entropy->next_restart_num++;
+      entropy->next_restart_num &= 7;
+    }
+    entropy->restarts_to_go--;
+  }
+
+  return TRUE;
+}
+
+
+/*
+ * MCU encoding for DC successive approximation refinement scan.
+ * Note: we assume such scans can be multi-component, although the spec
+ * is not very clear on the point.
+ */
+
+METHODDEF(boolean)
+encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+  register int temp;
+  int blkn;
+  int Al = cinfo->Al;
+  JBLOCKROW block;
+
+  entropy->next_output_byte = cinfo->dest->next_output_byte;
+  entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+  /* Emit restart marker if needed */
+  if (cinfo->restart_interval)
+    if (entropy->restarts_to_go == 0)
+      emit_restart(entropy, entropy->next_restart_num);
+
+  /* Encode the MCU data blocks */
+  for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+    block = MCU_data[blkn];
+
+    /* We simply emit the Al'th bit of the DC coefficient value. */
+    temp = (*block)[0];
+    emit_bits(entropy, (unsigned int) (temp >> Al), 1);
+  }
+
+  cinfo->dest->next_output_byte = entropy->next_output_byte;
+  cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+  /* Update restart-interval state too */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0) {
+      entropy->restarts_to_go = cinfo->restart_interval;
+      entropy->next_restart_num++;
+      entropy->next_restart_num &= 7;
+    }
+    entropy->restarts_to_go--;
+  }
+
+  return TRUE;
+}
+
+
+/*
+ * MCU encoding for AC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+  register int temp;
+  register int r, k;
+  int EOB;
+  char *BR_buffer;
+  unsigned int BR;
+  int Se = cinfo->Se;
+  int Al = cinfo->Al;
+  JBLOCKROW block;
+  int absvalues[DCTSIZE2];
+
+  entropy->next_output_byte = cinfo->dest->next_output_byte;
+  entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+  /* Emit restart marker if needed */
+  if (cinfo->restart_interval)
+    if (entropy->restarts_to_go == 0)
+      emit_restart(entropy, entropy->next_restart_num);
+
+  /* Encode the MCU data block */
+  block = MCU_data[0];
+
+  /* It is convenient to make a pre-pass to determine the transformed
+   * coefficients' absolute values and the EOB position.
+   */
+  EOB = 0;
+  for (k = cinfo->Ss; k <= Se; k++) {
+    temp = (*block)[jpeg_natural_order[k]];
+    /* We must apply the point transform by Al.  For AC coefficients this
+     * is an integer division with rounding towards 0.  To do this portably
+     * in C, we shift after obtaining the absolute value.
+     */
+    if (temp < 0)
+      temp = -temp;    /* temp is abs value of input */
+    temp >>= Al;    /* apply the point transform */
+    absvalues[k] = temp;  /* save abs value for main pass */
+    if (temp == 1)
+      EOB = k;      /* EOB = index of last newly-nonzero coef */
+  }
+
+  /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */
+  
+  r = 0;      /* r = run length of zeros */
+  BR = 0;      /* BR = count of buffered bits added now */
+  BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */
+
+  for (k = cinfo->Ss; k <= Se; k++) {
+    if ((temp = absvalues[k]) == 0) {
+      r++;
+      continue;
+    }
+
+    /* Emit any required ZRLs, but not if they can be folded into EOB */
+    while (r > 15 && k <= EOB) {
+      /* emit any pending EOBRUN and the BE correction bits */
+      emit_eobrun(entropy);
+      /* Emit ZRL */
+      emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
+      r -= 16;
+      /* Emit buffered correction bits that must be associated with ZRL */
+      emit_buffered_bits(entropy, BR_buffer, BR);
+      BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
+      BR = 0;
+    }
+
+    /* If the coef was previously nonzero, it only needs a correction bit.
+     * NOTE: a straight translation of the spec's figure G.7 would suggest
+     * that we also need to test r > 15.  But if r > 15, we can only get here
+     * if k > EOB, which implies that this coefficient is not 1.
+     */
+    if (temp > 1) {
+      /* The correction bit is the next bit of the absolute value. */
+      BR_buffer[BR++] = (char) (temp & 1);
+      continue;
+    }
+
+    /* Emit any pending EOBRUN and the BE correction bits */
+    emit_eobrun(entropy);
+
+    /* Count/emit Huffman symbol for run length / number of bits */
+    emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1);
+
+    /* Emit output bit for newly-nonzero coef */
+    temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1;
+    emit_bits(entropy, (unsigned int) temp, 1);
+
+    /* Emit buffered correction bits that must be associated with this code */
+    emit_buffered_bits(entropy, BR_buffer, BR);
+    BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
+    BR = 0;
+    r = 0;      /* reset zero run length */
+  }
+
+  if (r > 0 || BR > 0) {  /* If there are trailing zeroes, */
+    entropy->EOBRUN++;    /* count an EOB */
+    entropy->BE += BR;    /* concat my correction bits to older ones */
+    /* We force out the EOB if we risk either:
+     * 1. overflow of the EOB counter;
+     * 2. overflow of the correction bit buffer during the next MCU.
+     */
+    if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1))
+      emit_eobrun(entropy);
+  }
+
+  cinfo->dest->next_output_byte = entropy->next_output_byte;
+  cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+  /* Update restart-interval state too */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0) {
+      entropy->restarts_to_go = cinfo->restart_interval;
+      entropy->next_restart_num++;
+      entropy->next_restart_num &= 7;
+    }
+    entropy->restarts_to_go--;
+  }
+
+  return TRUE;
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed progressive scan.
+ */
+
+METHODDEF(void)
+finish_pass_phuff (j_compress_ptr cinfo)
+{   
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+
+  entropy->next_output_byte = cinfo->dest->next_output_byte;
+  entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+  /* Flush out any buffered data */
+  emit_eobrun(entropy);
+  flush_bits(entropy);
+
+  cinfo->dest->next_output_byte = entropy->next_output_byte;
+  cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+}
+
+
+/*
+ * Finish up a statistics-gathering pass and create the new Huffman tables.
+ */
+
+METHODDEF(void)
+finish_pass_gather_phuff (j_compress_ptr cinfo)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+  boolean is_DC_band;
+  int ci, tbl;
+  jpeg_component_info * compptr;
+  JHUFF_TBL **htblptr;
+  boolean did[NUM_HUFF_TBLS];
+
+  /* Flush out buffered data (all we care about is counting the EOB symbol) */
+  emit_eobrun(entropy);
+
+  is_DC_band = (cinfo->Ss == 0);
+
+  /* It's important not to apply jpeg_gen_optimal_table more than once
+   * per table, because it clobbers the input frequency counts!
+   */
+  MEMZERO(did, SIZEOF(did));
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    if (is_DC_band) {
+      if (cinfo->Ah != 0)  /* DC refinement needs no table */
+  continue;
+      tbl = compptr->dc_tbl_no;
+    } else {
+      tbl = compptr->ac_tbl_no;
+    }
+    if (! did[tbl]) {
+      if (is_DC_band)
+        htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
+      else
+        htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
+      if (*htblptr == NULL)
+        *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+      jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]);
+      did[tbl] = TRUE;
+    }
+  }
+}
+
+
+METHODDEF(boolean)
+need_optimization_pass (j_compress_ptr cinfo)
+{
+  return (cinfo->Ss != 0 || cinfo->Ah == 0);
+}
+
+
+/*
+ * Module initialization routine for progressive Huffman entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_phuff_encoder (j_compress_ptr cinfo)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy;
+  int i;
+
+  entropy = (phuff_entropy_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(phuff_entropy_encoder));
+  lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy;
+  lossyc->pub.entropy_start_pass = start_pass_phuff;
+  lossyc->pub.need_optimization_pass = need_optimization_pass;
+
+  /* Mark tables unallocated */
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    entropy->derived_tbls[i] = NULL;
+    entropy->count_ptrs[i] = NULL;
+  }
+  entropy->bit_buffer = NULL;  /* needed only in AC refinement scan */
+}
+
+#endif /* C_PROGRESSIVE_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcpred.c b/Utilities/ITK/Utilities/itkjpeg/jcpred.c
new file mode 100644
index 0000000000000000000000000000000000000000..293596c1b9053e9605940631f7ca24282942fcaf
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcpred.c
@@ -0,0 +1,301 @@
+/*
+ * jcpred.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains sample differencing for lossless JPEG.
+ *
+ * In order to avoid paying the performance penalty of having to check the
+ * predictor being used and the row being processed for each call of the
+ * undifferencer, and to promote optimization, we have separate differencing
+ * functions for each case.
+ *
+ * We are able to avoid duplicating source code by implementing the predictors
+ * and differencers as macros.  Each of the differencing functions are
+ * simply wrappers around a DIFFERENCE macro with the appropriate PREDICTOR
+ * macro passed as an argument.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossls.h"    /* Private declarations for lossless codec */
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+/* Private predictor object */
+
+typedef struct {
+  /* MCU-rows left in the restart interval for each component */
+  unsigned int restart_rows_to_go[MAX_COMPONENTS];
+} c_predictor;
+
+typedef c_predictor * c_pred_ptr;
+
+/* Forward declarations */
+LOCAL(void) reset_predictor
+  JPP((j_compress_ptr cinfo, int ci));
+METHODDEF(void) start_pass
+  JPP((j_compress_ptr cinfo));
+
+
+/* Predictor for the first column of the first row: 2^(P-Pt-1) */
+#define INITIAL_PREDICTORx  (1 << (cinfo->data_precision - cinfo->Al - 1))
+
+/* Predictor for the first column of the remaining rows: Rb */
+#define INITIAL_PREDICTOR2  GETJSAMPLE(prev_row[0])
+
+
+/*
+ * 1-Dimensional differencer routine.
+ *
+ * This macro implements the 1-D horizontal predictor (1).  INITIAL_PREDICTOR
+ * is used as the special case predictor for the first column, which must be
+ * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx.  The remaining samples
+ * use PREDICTOR1.
+ */
+
+#define DIFFERENCE_1D(INITIAL_PREDICTOR) \
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \
+  c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \
+  boolean restart = FALSE; \
+  unsigned int xindex; \
+  int samp, Ra; \
+ \
+  samp = GETJSAMPLE(input_buf[0]); \
+  diff_buf[0] = samp - INITIAL_PREDICTOR; \
+ \
+  for (xindex = 1; xindex < width; xindex++) { \
+    Ra = samp; \
+    samp = GETJSAMPLE(input_buf[xindex]); \
+    diff_buf[xindex] = samp - PREDICTOR1; \
+  } \
+ \
+  /* Account for restart interval (no-op if not using restarts) */ \
+  if (cinfo->restart_interval) { \
+    if (--(pred->restart_rows_to_go[ci]) == 0) { \
+      reset_predictor(cinfo, ci); \
+      restart = TRUE; \
+    } \
+  }
+
+
+/*
+ * 2-Dimensional differencer routine.
+ *
+ * This macro implements the 2-D horizontal predictors (#2-7).  PREDICTOR2 is
+ * used as the special case predictor for the first column.  The remaining
+ * samples use PREDICTOR, which is a function of Ra, Rb, Rc.
+ *
+ * Because prev_row and output_buf may point to the same storage area (in an
+ * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc
+ * before writing the current reconstructed sample value into output_buf.
+ */
+
+#define DIFFERENCE_2D(PREDICTOR) \
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \
+  c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \
+  unsigned int xindex; \
+  int samp, Ra, Rb, Rc; \
+ \
+  Rb = GETJSAMPLE(prev_row[0]); \
+  samp = GETJSAMPLE(input_buf[0]); \
+  diff_buf[0] = samp - PREDICTOR2; \
+ \
+  for (xindex = 1; xindex < width; xindex++) { \
+    Rc = Rb; \
+    Rb = GETJSAMPLE(prev_row[xindex]); \
+    Ra = samp; \
+    samp = GETJSAMPLE(input_buf[xindex]); \
+    diff_buf[xindex] = samp - PREDICTOR; \
+  } \
+ \
+  /* Account for restart interval (no-op if not using restarts) */ \
+  if (cinfo->restart_interval) { \
+    if (--pred->restart_rows_to_go[ci] == 0) \
+      reset_predictor(cinfo, ci); \
+  }
+
+
+/*
+ * Differencers for the all rows but the first in a scan or restart interval.
+ * The first sample in the row is differenced using the vertical
+ * predictor (2).  The rest of the samples are differenced using the
+ * predictor specified in the scan header.
+ */
+
+METHODDEF(void)
+jpeg_difference1(j_compress_ptr cinfo, int ci,
+     JSAMPROW input_buf, JSAMPROW prev_row,
+     JDIFFROW diff_buf, JDIMENSION width)
+{
+  DIFFERENCE_1D(INITIAL_PREDICTOR2);
+}
+
+METHODDEF(void)
+jpeg_difference2(j_compress_ptr cinfo, int ci,
+     JSAMPROW input_buf, JSAMPROW prev_row,
+     JDIFFROW diff_buf, JDIMENSION width)
+{
+  DIFFERENCE_2D(PREDICTOR2);
+}
+
+METHODDEF(void)
+jpeg_difference3(j_compress_ptr cinfo, int ci,
+     JSAMPROW input_buf, JSAMPROW prev_row,
+     JDIFFROW diff_buf, JDIMENSION width)
+{
+  DIFFERENCE_2D(PREDICTOR3);
+}
+
+METHODDEF(void)
+jpeg_difference4(j_compress_ptr cinfo, int ci,
+     JSAMPROW input_buf, JSAMPROW prev_row,
+     JDIFFROW diff_buf, JDIMENSION width)
+{
+  DIFFERENCE_2D(PREDICTOR4);
+}
+
+METHODDEF(void)
+jpeg_difference5(j_compress_ptr cinfo, int ci,
+     JSAMPROW input_buf, JSAMPROW prev_row,
+     JDIFFROW diff_buf, JDIMENSION width)
+{
+  SHIFT_TEMPS
+  DIFFERENCE_2D(PREDICTOR5);
+}
+
+METHODDEF(void)
+jpeg_difference6(j_compress_ptr cinfo, int ci,
+     JSAMPROW input_buf, JSAMPROW prev_row,
+     JDIFFROW diff_buf, JDIMENSION width)
+{
+  SHIFT_TEMPS
+  DIFFERENCE_2D(PREDICTOR6);
+}
+
+METHODDEF(void)
+jpeg_difference7(j_compress_ptr cinfo, int ci,
+     JSAMPROW input_buf, JSAMPROW prev_row,
+     JDIFFROW diff_buf, JDIMENSION width)
+{
+  SHIFT_TEMPS
+  DIFFERENCE_2D(PREDICTOR7);
+}
+
+
+/*
+ * Differencer for the first row in a scan or restart interval.  The first
+ * sample in the row is differenced using the special predictor constant
+ * x=2^(P-Pt-1).  The rest of the samples are differenced using the
+ * 1-D horizontal predictor (1).
+ */
+
+METHODDEF(void)
+jpeg_difference_first_row(j_compress_ptr cinfo, int ci,
+     JSAMPROW input_buf, JSAMPROW prev_row,
+     JDIFFROW diff_buf, JDIMENSION width)
+{
+  DIFFERENCE_1D(INITIAL_PREDICTORx);
+  (void)prev_row;
+
+  /*
+   * Now that we have differenced the first row, we want to use the
+   * differencer which corresponds to the predictor specified in the
+   * scan header.
+   *
+   * Note that we don't to do this if we have just reset the predictor
+   * for a new restart interval.
+   */
+  if (!restart) {
+    switch (cinfo->Ss) {
+    case 1:
+      losslsc->predict_difference[ci] = jpeg_difference1;
+      break;
+    case 2:
+      losslsc->predict_difference[ci] = jpeg_difference2;
+      break;
+    case 3:
+      losslsc->predict_difference[ci] = jpeg_difference3;
+      break;
+    case 4:
+      losslsc->predict_difference[ci] = jpeg_difference4;
+      break;
+    case 5:
+      losslsc->predict_difference[ci] = jpeg_difference5;
+      break;
+    case 6:
+      losslsc->predict_difference[ci] = jpeg_difference6;
+      break;
+    case 7:
+      losslsc->predict_difference[ci] = jpeg_difference7;
+      break;
+    }
+  }
+}
+
+/*
+ * Reset predictor at the start of a pass or restart interval.
+ */
+
+LOCAL(void)
+reset_predictor (j_compress_ptr cinfo, int ci)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private;
+
+  /* Initialize restart counter */
+  pred->restart_rows_to_go[ci] =
+    cinfo->restart_interval / cinfo->MCUs_per_row;
+
+  /* Set difference function to first row function */
+  losslsc->predict_difference[ci] = jpeg_difference_first_row;
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_pass (j_compress_ptr cinfo)
+{
+  /* j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; */
+  /* c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; */
+  int ci;
+
+  /* Check that the restart interval is an integer multiple of the number 
+   * of MCU in an MCU-row.
+   */
+  if (cinfo->restart_interval % cinfo->MCUs_per_row != 0)
+    ERREXIT2(cinfo, JERR_BAD_RESTART,
+       cinfo->restart_interval, cinfo->MCUs_per_row);
+
+  /* Set predictors for start of pass */
+  for (ci = 0; ci < cinfo->num_components; ci++)
+    reset_predictor(cinfo, ci);
+}
+
+
+/*
+ * Module initialization routine for the differencer.
+ */
+
+GLOBAL(void)
+jinit_differencer (j_compress_ptr cinfo)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+  c_pred_ptr pred;
+
+  pred = (c_pred_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(c_predictor));
+  losslsc->pred_private = (void *) pred;
+  losslsc->predict_start_pass = start_pass;
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
+
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcprepct.c b/Utilities/ITK/Utilities/itkjpeg/jcprepct.c
new file mode 100644
index 0000000000000000000000000000000000000000..188548194a2f13949691437a81dad4d28503199e
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcprepct.c
@@ -0,0 +1,354 @@
+/*
+ * jcprepct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the compression preprocessing controller.
+ * This controller manages the color conversion, downsampling,
+ * and edge expansion steps.
+ *
+ * Most of the complexity here is associated with buffering input rows
+ * as required by the downsampler.  See the comments at the head of
+ * jcsample.c for the downsampler's needs.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* At present, jcsample.c can request context rows only for smoothing.
+ * In the future, we might also need context rows for CCIR601 sampling
+ * or other more-complex downsampling procedures.  The code to support
+ * context rows should be compiled only if needed.
+ */
+#ifdef INPUT_SMOOTHING_SUPPORTED
+#define CONTEXT_ROWS_SUPPORTED
+#endif
+
+
+/*
+ * For the simple (no-context-row) case, we just need to buffer one
+ * row group's worth of pixels for the downsampling step.  At the bottom of
+ * the image, we pad to a full row group by replicating the last pixel row.
+ * The downsampler's last output row is then replicated if needed to pad
+ * out to a full iMCU row.
+ *
+ * When providing context rows, we must buffer three row groups' worth of
+ * pixels.  Three row groups are physically allocated, but the row pointer
+ * arrays are made five row groups high, with the extra pointers above and
+ * below "wrapping around" to point to the last and first real row groups.
+ * This allows the downsampler to access the proper context rows.
+ * At the top and bottom of the image, we create dummy context rows by
+ * copying the first or last real pixel row.  This copying could be avoided
+ * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
+ * trouble on the compression side.
+ */
+
+
+/* Private buffer controller object */
+
+typedef struct {
+  struct jpeg_c_prep_controller pub; /* public fields */
+
+  /* Downsampling input buffer.  This buffer holds color-converted data
+   * until we have enough to do a downsample step.
+   */
+  JSAMPARRAY color_buf[MAX_COMPONENTS];
+
+  JDIMENSION rows_to_go;  /* counts rows remaining in source image */
+  int next_buf_row;    /* index of next row to store in color_buf */
+
+#ifdef CONTEXT_ROWS_SUPPORTED  /* only needed for context case */
+  int this_row_group;    /* starting row index of group to process */
+  int next_buf_stop;    /* downsample when we reach this index */
+#endif
+} my_prep_controller;
+
+typedef my_prep_controller * my_prep_ptr;
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+
+  if (pass_mode != JBUF_PASS_THRU)
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+  /* Initialize total-height counter for detecting bottom of image */
+  prep->rows_to_go = cinfo->image_height;
+  /* Mark the conversion buffer empty */
+  prep->next_buf_row = 0;
+#ifdef CONTEXT_ROWS_SUPPORTED
+  /* Preset additional state variables for context mode.
+   * These aren't used in non-context mode, so we needn't test which mode.
+   */
+  prep->this_row_group = 0;
+  /* Set next_buf_stop to stop after two row groups have been read in. */
+  prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
+#endif
+}
+
+
+/*
+ * Expand an image vertically from height input_rows to height output_rows,
+ * by duplicating the bottom row.
+ */
+
+LOCAL(void)
+expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
+        int input_rows, int output_rows)
+{
+  register int row;
+
+  for (row = input_rows; row < output_rows; row++) {
+    jcopy_sample_rows(image_data, input_rows-1, image_data, row,
+          1, num_cols);
+  }
+}
+
+
+/*
+ * Process some data in the simple no-context case.
+ *
+ * Preprocessor output data is counted in "row groups".  A row group
+ * is defined to be v_samp_factor sample rows of each component.
+ * Downsampling will produce this much data from each max_v_samp_factor
+ * input rows.
+ */
+
+METHODDEF(void)
+pre_process_data (j_compress_ptr cinfo,
+      JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+      JDIMENSION in_rows_avail,
+      JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+      JDIMENSION out_row_groups_avail)
+{
+  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+  int numrows, ci;
+  JDIMENSION inrows;
+  jpeg_component_info * compptr;
+
+  while (*in_row_ctr < in_rows_avail &&
+   *out_row_group_ctr < out_row_groups_avail) {
+    /* Do color conversion to fill the conversion buffer. */
+    inrows = in_rows_avail - *in_row_ctr;
+    numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
+    numrows = (int) MIN((JDIMENSION) numrows, inrows);
+    (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
+               prep->color_buf,
+               (JDIMENSION) prep->next_buf_row,
+               numrows);
+    *in_row_ctr += numrows;
+    prep->next_buf_row += numrows;
+    prep->rows_to_go -= numrows;
+    /* If at bottom of image, pad to fill the conversion buffer. */
+    if (prep->rows_to_go == 0 &&
+  prep->next_buf_row < cinfo->max_v_samp_factor) {
+      for (ci = 0; ci < cinfo->num_components; ci++) {
+  expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
+         prep->next_buf_row, cinfo->max_v_samp_factor);
+      }
+      prep->next_buf_row = cinfo->max_v_samp_factor;
+    }
+    /* If we've filled the conversion buffer, empty it. */
+    if (prep->next_buf_row == cinfo->max_v_samp_factor) {
+      (*cinfo->downsample->downsample) (cinfo,
+          prep->color_buf, (JDIMENSION) 0,
+          output_buf, *out_row_group_ctr);
+      prep->next_buf_row = 0;
+      (*out_row_group_ctr)++;
+    }
+    /* If at bottom of image, pad the output to a full iMCU height.
+     * Note we assume the caller is providing a one-iMCU-height output buffer!
+     */
+    if (prep->rows_to_go == 0 &&
+  *out_row_group_ctr < out_row_groups_avail) {
+      for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+     ci++, compptr++) {
+  expand_bottom_edge(output_buf[ci],
+         compptr->width_in_data_units * cinfo->data_unit,
+         (int) (*out_row_group_ctr * compptr->v_samp_factor),
+         (int) (out_row_groups_avail * compptr->v_samp_factor));
+      }
+      *out_row_group_ctr = out_row_groups_avail;
+      break;      /* can exit outer loop without test */
+    }
+  }
+}
+
+
+#ifdef CONTEXT_ROWS_SUPPORTED
+
+/*
+ * Process some data in the context case.
+ */
+
+METHODDEF(void)
+pre_process_context (j_compress_ptr cinfo,
+         JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+         JDIMENSION in_rows_avail,
+         JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+         JDIMENSION out_row_groups_avail)
+{
+  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+  int numrows, ci;
+  int buf_height = cinfo->max_v_samp_factor * 3;
+  JDIMENSION inrows;
+
+  while (*out_row_group_ctr < out_row_groups_avail) {
+    if (*in_row_ctr < in_rows_avail) {
+      /* Do color conversion to fill the conversion buffer. */
+      inrows = in_rows_avail - *in_row_ctr;
+      numrows = prep->next_buf_stop - prep->next_buf_row;
+      numrows = (int) MIN((JDIMENSION) numrows, inrows);
+      (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
+           prep->color_buf,
+           (JDIMENSION) prep->next_buf_row,
+           numrows);
+      /* Pad at top of image, if first time through */
+      if (prep->rows_to_go == cinfo->image_height) {
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    int row;
+    for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
+      jcopy_sample_rows(prep->color_buf[ci], 0,
+            prep->color_buf[ci], -row,
+            1, cinfo->image_width);
+    }
+  }
+      }
+      *in_row_ctr += numrows;
+      prep->next_buf_row += numrows;
+      prep->rows_to_go -= numrows;
+    } else {
+      /* Return for more data, unless we are at the bottom of the image. */
+      if (prep->rows_to_go != 0)
+  break;
+      /* When at bottom of image, pad to fill the conversion buffer. */
+      if (prep->next_buf_row < prep->next_buf_stop) {
+  for (ci = 0; ci < cinfo->num_components; ci++) {
+    expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
+           prep->next_buf_row, prep->next_buf_stop);
+  }
+  prep->next_buf_row = prep->next_buf_stop;
+      }
+    }
+    /* If we've gotten enough data, downsample a row group. */
+    if (prep->next_buf_row == prep->next_buf_stop) {
+      (*cinfo->downsample->downsample) (cinfo,
+          prep->color_buf,
+          (JDIMENSION) prep->this_row_group,
+          output_buf, *out_row_group_ctr);
+      (*out_row_group_ctr)++;
+      /* Advance pointers with wraparound as necessary. */
+      prep->this_row_group += cinfo->max_v_samp_factor;
+      if (prep->this_row_group >= buf_height)
+  prep->this_row_group = 0;
+      if (prep->next_buf_row >= buf_height)
+  prep->next_buf_row = 0;
+      prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
+    }
+  }
+}
+
+
+/*
+ * Create the wrapped-around downsampling input buffer needed for context mode.
+ */
+
+LOCAL(void)
+create_context_buffer (j_compress_ptr cinfo)
+{
+  my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+  int rgroup_height = cinfo->max_v_samp_factor;
+  int ci, i;
+  jpeg_component_info * compptr;
+  JSAMPARRAY true_buffer, fake_buffer;
+
+  /* Grab enough space for fake row pointers for all the components;
+   * we need five row groups' worth of pointers for each component.
+   */
+  fake_buffer = (JSAMPARRAY)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        (cinfo->num_components * 5 * rgroup_height) *
+        SIZEOF(JSAMPROW));
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Allocate the actual buffer space (3 row groups) for this component.
+     * We make the buffer wide enough to allow the downsampler to edge-expand
+     * horizontally within the buffer, if it so chooses.
+     */
+    true_buffer = (*cinfo->mem->alloc_sarray)
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit *
+          cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+       (JDIMENSION) (3 * rgroup_height));
+    /* Copy true buffer row pointers into the middle of the fake row array */
+    MEMCOPY(fake_buffer + rgroup_height, true_buffer,
+      3 * rgroup_height * SIZEOF(JSAMPROW));
+    /* Fill in the above and below wraparound pointers */
+    for (i = 0; i < rgroup_height; i++) {
+      fake_buffer[i] = true_buffer[2 * rgroup_height + i];
+      fake_buffer[4 * rgroup_height + i] = true_buffer[i];
+    }
+    prep->color_buf[ci] = fake_buffer + rgroup_height;
+    fake_buffer += 5 * rgroup_height; /* point to space for next component */
+  }
+}
+
+#endif /* CONTEXT_ROWS_SUPPORTED */
+
+
+/*
+ * Initialize preprocessing controller.
+ */
+
+GLOBAL(void)
+jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+  my_prep_ptr prep;
+  int ci;
+  jpeg_component_info * compptr;
+
+  if (need_full_buffer)    /* safety check */
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+  prep = (my_prep_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_prep_controller));
+  cinfo->prep = (struct jpeg_c_prep_controller *) prep;
+  prep->pub.start_pass = start_pass_prep;
+
+  /* Allocate the color conversion buffer.
+   * We make the buffer wide enough to allow the downsampler to edge-expand
+   * horizontally within the buffer, if it so chooses.
+   */
+  if (cinfo->downsample->need_context_rows) {
+    /* Set up to provide context rows */
+#ifdef CONTEXT_ROWS_SUPPORTED
+    prep->pub.pre_process_data = pre_process_context;
+    create_context_buffer(cinfo);
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+  } else {
+    /* No context, just make it tall enough for one row group */
+    prep->pub.pre_process_data = pre_process_data;
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
+  ((j_common_ptr) cinfo, JPOOL_IMAGE,
+   (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit *
+      cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+   (JDIMENSION) cinfo->max_v_samp_factor);
+    }
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcsample.c b/Utilities/ITK/Utilities/itkjpeg/jcsample.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b5fb79e4a086b4dc113fa0a4faea9da193a635c
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcsample.c
@@ -0,0 +1,520 @@
+/*
+ * jcsample.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains downsampling routines.
+ *
+ * Downsampling input data is counted in "row groups".  A row group
+ * is defined to be max_v_samp_factor pixel rows of each component,
+ * from which the downsampler produces v_samp_factor sample rows.
+ * A single row group is processed in each call to the downsampler module.
+ *
+ * The downsampler is responsible for edge-expansion of its output data
+ * to fill an integral number of DCT blocks horizontally.  The source buffer
+ * may be modified if it is helpful for this purpose (the source buffer is
+ * allocated wide enough to correspond to the desired output width).
+ * The caller (the prep controller) is responsible for vertical padding.
+ *
+ * The downsampler may request "context rows" by setting need_context_rows
+ * during startup.  In this case, the input arrays will contain at least
+ * one row group's worth of pixels above and below the passed-in data;
+ * the caller will create dummy rows at image top and bottom by replicating
+ * the first or last real pixel row.
+ *
+ * An excellent reference for image resampling is
+ *   Digital Image Warping, George Wolberg, 1990.
+ *   Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
+ *
+ * The downsampling algorithm used here is a simple average of the source
+ * pixels covered by the output pixel.  The hi-falutin sampling literature
+ * refers to this as a "box filter".  In general the characteristics of a box
+ * filter are not very good, but for the specific cases we normally use (1:1
+ * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
+ * nearly so bad.  If you intend to use other sampling ratios, you'd be well
+ * advised to improve this code.
+ *
+ * A simple input-smoothing capability is provided.  This is mainly intended
+ * for cleaning up color-dithered GIF input files (if you find it inadequate,
+ * we suggest using an external filtering program such as pnmconvol).  When
+ * enabled, each input pixel P is replaced by a weighted sum of itself and its
+ * eight neighbors.  P's weight is 1-8*SF and each neighbor's weight is SF,
+ * where SF = (smoothing_factor / 1024).
+ * Currently, smoothing is only supported for 2h2v sampling factors.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Pointer to routine to downsample a single component */
+typedef JMETHOD(void, downsample1_ptr,
+    (j_compress_ptr cinfo, jpeg_component_info * compptr,
+     JSAMPARRAY input_data, JSAMPARRAY output_data));
+
+/* Private subobject */
+
+typedef struct {
+  struct jpeg_downsampler pub;  /* public fields */
+
+  /* Downsampling method pointers, one per component */
+  downsample1_ptr methods[MAX_COMPONENTS];
+} my_downsampler;
+
+typedef my_downsampler * my_downsample_ptr;
+
+
+/*
+ * Initialize for a downsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_downsample (j_compress_ptr cinfo)
+{
+  (void)cinfo;
+  /* no work for now */
+}
+
+
+/*
+ * Expand a component horizontally from width input_cols to width output_cols,
+ * by duplicating the rightmost samples.
+ */
+
+LOCAL(void)
+expand_right_edge (JSAMPARRAY image_data, int num_rows,
+       JDIMENSION input_cols, JDIMENSION output_cols)
+{
+  register JSAMPROW ptr;
+  register JSAMPLE pixval;
+  register int count;
+  int row;
+  int numcols = (int) (output_cols - input_cols);
+
+  if (numcols > 0) {
+    for (row = 0; row < num_rows; row++) {
+      ptr = image_data[row] + input_cols;
+      pixval = ptr[-1];    /* don't need GETJSAMPLE() here */
+      for (count = numcols; count > 0; count--)
+  *ptr++ = pixval;
+    }
+  }
+}
+
+
+/*
+ * Do downsampling for a whole row group (all components).
+ *
+ * In this version we simply downsample each component independently.
+ */
+
+METHODDEF(void)
+sep_downsample (j_compress_ptr cinfo,
+    JSAMPIMAGE input_buf, JDIMENSION in_row_index,
+    JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
+{
+  my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
+  int ci;
+  jpeg_component_info * compptr;
+  JSAMPARRAY in_ptr, out_ptr;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    in_ptr = input_buf[ci] + in_row_index;
+    out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);
+    (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
+  }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * One row group is processed per call.
+ * This version handles arbitrary integral sampling ratios, without smoothing.
+ * Note that this version is not actually used for customary sampling ratios.
+ */
+
+METHODDEF(void)
+int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+    JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+  int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
+  JDIMENSION outcol, outcol_h;  /* outcol_h == outcol*h_expand */
+  JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
+  JSAMPROW inptr, outptr;
+  INT32 outvalue;
+
+  h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
+  v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
+  numpix = h_expand * v_expand;
+  numpix2 = numpix/2;
+
+  /* Expand input data enough to let all the output samples be generated
+   * by the standard loop.  Special-casing padded output would be more
+   * efficient.
+   */
+  expand_right_edge(input_data, cinfo->max_v_samp_factor,
+        cinfo->image_width, output_cols * h_expand);
+
+  inrow = 0;
+  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+    outptr = output_data[outrow];
+    for (outcol = 0, outcol_h = 0; outcol < output_cols;
+   outcol++, outcol_h += h_expand) {
+      outvalue = 0;
+      for (v = 0; v < v_expand; v++) {
+  inptr = input_data[inrow+v] + outcol_h;
+  for (h = 0; h < h_expand; h++) {
+    outvalue += (INT32) GETJSAMPLE(*inptr++);
+  }
+      }
+      *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
+    }
+    inrow += v_expand;
+  }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the special case of a full-size component,
+ * without smoothing.
+ */
+
+METHODDEF(void)
+fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+         JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+  /* Copy the data */
+  jcopy_sample_rows(input_data, 0, output_data, 0,
+        cinfo->max_v_samp_factor, cinfo->image_width);
+  /* Edge-expand */
+  expand_right_edge(output_data, cinfo->max_v_samp_factor,
+        cinfo->image_width, compptr->width_in_data_units * cinfo->data_unit);
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the common case of 2:1 horizontal and 1:1 vertical,
+ * without smoothing.
+ *
+ * A note about the "bias" calculations: when rounding fractional values to
+ * integer, we do not want to always round 0.5 up to the next integer.
+ * If we did that, we'd introduce a noticeable bias towards larger values.
+ * Instead, this code is arranged so that 0.5 will be rounded up or down at
+ * alternate pixel locations (a simple ordered dither pattern).
+ */
+
+METHODDEF(void)
+h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+     JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+  int outrow;
+  JDIMENSION outcol;
+  JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
+  register JSAMPROW inptr, outptr;
+  register int bias;
+
+  /* Expand input data enough to let all the output samples be generated
+   * by the standard loop.  Special-casing padded output would be more
+   * efficient.
+   */
+  expand_right_edge(input_data, cinfo->max_v_samp_factor,
+        cinfo->image_width, output_cols * 2);
+
+  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+    outptr = output_data[outrow];
+    inptr = input_data[outrow];
+    bias = 0;      /* bias = 0,1,0,1,... for successive samples */
+    for (outcol = 0; outcol < output_cols; outcol++) {
+      *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
+            + bias) >> 1);
+      bias ^= 1;    /* 0=>1, 1=>0 */
+      inptr += 2;
+    }
+  }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
+ * without smoothing.
+ */
+
+METHODDEF(void)
+h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+     JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+  int inrow, outrow;
+  JDIMENSION outcol;
+  JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
+  register JSAMPROW inptr0, inptr1, outptr;
+  register int bias;
+
+  /* Expand input data enough to let all the output samples be generated
+   * by the standard loop.  Special-casing padded output would be more
+   * efficient.
+   */
+  expand_right_edge(input_data, cinfo->max_v_samp_factor,
+        cinfo->image_width, output_cols * 2);
+
+  inrow = 0;
+  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+    outptr = output_data[outrow];
+    inptr0 = input_data[inrow];
+    inptr1 = input_data[inrow+1];
+    bias = 1;      /* bias = 1,2,1,2,... for successive samples */
+    for (outcol = 0; outcol < output_cols; outcol++) {
+      *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+            GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
+            + bias) >> 2);
+      bias ^= 3;    /* 1=>2, 2=>1 */
+      inptr0 += 2; inptr1 += 2;
+    }
+    inrow += 2;
+  }
+}
+
+
+#ifdef INPUT_SMOOTHING_SUPPORTED
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
+ * with smoothing.  One row of context is required.
+ */
+
+METHODDEF(void)
+h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+      JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+  int inrow, outrow;
+  JDIMENSION colctr;
+  JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
+  register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
+  INT32 membersum, neighsum, memberscale, neighscale;
+
+  /* Expand input data enough to let all the output samples be generated
+   * by the standard loop.  Special-casing padded output would be more
+   * efficient.
+   */
+  expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
+        cinfo->image_width, output_cols * 2);
+
+  /* We don't bother to form the individual "smoothed" input pixel values;
+   * we can directly compute the output which is the average of the four
+   * smoothed values.  Each of the four member pixels contributes a fraction
+   * (1-8*SF) to its own smoothed image and a fraction SF to each of the three
+   * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
+   * output.  The four corner-adjacent neighbor pixels contribute a fraction
+   * SF to just one smoothed pixel, or SF/4 to the final output; while the
+   * eight edge-adjacent neighbors contribute SF to each of two smoothed
+   * pixels, or SF/2 overall.  In order to use integer arithmetic, these
+   * factors are scaled by 2^16 = 65536.
+   * Also recall that SF = smoothing_factor / 1024.
+   */
+
+  memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */
+  neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
+
+  inrow = 0;
+  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+    outptr = output_data[outrow];
+    inptr0 = input_data[inrow];
+    inptr1 = input_data[inrow+1];
+    above_ptr = input_data[inrow-1];
+    below_ptr = input_data[inrow+2];
+
+    /* Special case for first column: pretend column -1 is same as column 0 */
+    membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+    GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+    neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+         GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+         GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
+         GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
+    neighsum += neighsum;
+    neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
+    GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
+    membersum = membersum * memberscale + neighsum * neighscale;
+    *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+    inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+
+    for (colctr = output_cols - 2; colctr > 0; colctr--) {
+      /* sum of pixels directly mapped to this output element */
+      membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+      GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+      /* sum of edge-neighbor pixels */
+      neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+     GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+     GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
+     GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
+      /* The edge-neighbors count twice as much as corner-neighbors */
+      neighsum += neighsum;
+      /* Add in the corner-neighbors */
+      neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
+      GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
+      /* form final output scaled up by 2^16 */
+      membersum = membersum * memberscale + neighsum * neighscale;
+      /* round, descale and output it */
+      *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+      inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+    }
+
+    /* Special case for last column */
+    membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+    GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+    neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+         GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+         GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
+         GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
+    neighsum += neighsum;
+    neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
+    GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
+    membersum = membersum * memberscale + neighsum * neighscale;
+    *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+
+    inrow += 2;
+  }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the special case of a full-size component,
+ * with smoothing.  One row of context is required.
+ */
+
+METHODDEF(void)
+fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
+          JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+  int outrow;
+  JDIMENSION colctr;
+  JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
+  register JSAMPROW inptr, above_ptr, below_ptr, outptr;
+  INT32 membersum, neighsum, memberscale, neighscale;
+  int colsum, lastcolsum, nextcolsum;
+
+  /* Expand input data enough to let all the output samples be generated
+   * by the standard loop.  Special-casing padded output would be more
+   * efficient.
+   */
+  expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
+        cinfo->image_width, output_cols);
+
+  /* Each of the eight neighbor pixels contributes a fraction SF to the
+   * smoothed pixel, while the main pixel contributes (1-8*SF).  In order
+   * to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
+   * Also recall that SF = smoothing_factor / 1024.
+   */
+
+  memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
+  neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
+
+  for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+    outptr = output_data[outrow];
+    inptr = input_data[outrow];
+    above_ptr = input_data[outrow-1];
+    below_ptr = input_data[outrow+1];
+
+    /* Special case for first column */
+    colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
+       GETJSAMPLE(*inptr);
+    membersum = GETJSAMPLE(*inptr++);
+    nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
+     GETJSAMPLE(*inptr);
+    neighsum = colsum + (colsum - membersum) + nextcolsum;
+    membersum = membersum * memberscale + neighsum * neighscale;
+    *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+    lastcolsum = colsum; colsum = nextcolsum;
+
+    for (colctr = output_cols - 2; colctr > 0; colctr--) {
+      membersum = GETJSAMPLE(*inptr++);
+      above_ptr++; below_ptr++;
+      nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
+       GETJSAMPLE(*inptr);
+      neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
+      membersum = membersum * memberscale + neighsum * neighscale;
+      *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+      lastcolsum = colsum; colsum = nextcolsum;
+    }
+
+    /* Special case for last column */
+    membersum = GETJSAMPLE(*inptr);
+    neighsum = lastcolsum + (colsum - membersum) + colsum;
+    membersum = membersum * memberscale + neighsum * neighscale;
+    *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+
+  }
+}
+
+#endif /* INPUT_SMOOTHING_SUPPORTED */
+
+
+/*
+ * Module initialization routine for downsampling.
+ * Note that we must select a routine for each component.
+ */
+
+GLOBAL(void)
+jinit_downsampler (j_compress_ptr cinfo)
+{
+  my_downsample_ptr downsample;
+  int ci;
+  jpeg_component_info * compptr;
+  boolean smoothok = TRUE;
+
+  downsample = (my_downsample_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_downsampler));
+  cinfo->downsample = (struct jpeg_downsampler *) downsample;
+  downsample->pub.start_pass = start_pass_downsample;
+  downsample->pub.downsample = sep_downsample;
+  downsample->pub.need_context_rows = FALSE;
+
+  if (cinfo->CCIR601_sampling)
+    ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
+
+  /* Verify we can handle the sampling factors, and set up method pointers */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
+  compptr->v_samp_factor == cinfo->max_v_samp_factor) {
+#ifdef INPUT_SMOOTHING_SUPPORTED
+      if (cinfo->smoothing_factor) {
+  downsample->methods[ci] = fullsize_smooth_downsample;
+  downsample->pub.need_context_rows = TRUE;
+      } else
+#endif
+  downsample->methods[ci] = fullsize_downsample;
+    } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
+         compptr->v_samp_factor == cinfo->max_v_samp_factor) {
+      smoothok = FALSE;
+      downsample->methods[ci] = h2v1_downsample;
+    } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
+         compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {
+#ifdef INPUT_SMOOTHING_SUPPORTED
+      if (cinfo->smoothing_factor) {
+  downsample->methods[ci] = h2v2_smooth_downsample;
+  downsample->pub.need_context_rows = TRUE;
+      } else
+#endif
+  downsample->methods[ci] = h2v2_downsample;
+    } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
+         (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {
+      smoothok = FALSE;
+      downsample->methods[ci] = int_downsample;
+    } else
+      ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
+  }
+
+#ifdef INPUT_SMOOTHING_SUPPORTED
+  if (cinfo->smoothing_factor && !smoothok)
+    TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
+#endif
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcscale.c b/Utilities/ITK/Utilities/itkjpeg/jcscale.c
new file mode 100644
index 0000000000000000000000000000000000000000..f0539afed68738f7f0ed35cc34b96326801a0066
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcscale.c
@@ -0,0 +1,64 @@
+/*
+ * jcscale.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains sample downscaling by 2^Pt for lossless JPEG.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossls.h"    /* Private declarations for lossless codec */
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+METHODDEF(void)
+simple_downscale(j_compress_ptr cinfo,
+     JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width)
+{
+  /* j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; */
+  unsigned int xindex;
+  SHIFT_TEMPS
+
+  for (xindex = 0; xindex < width; xindex++)
+    output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(GETJSAMPLE(input_buf[xindex]),
+                 cinfo->Al);
+}
+
+
+METHODDEF(void)
+noscale(j_compress_ptr cinfo,
+  JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width)
+{
+  (void)cinfo;
+  MEMCOPY(output_buf, input_buf, width * SIZEOF(JSAMPLE));
+  return;
+}
+
+
+METHODDEF(void)
+scaler_start_pass (j_compress_ptr cinfo)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+
+  /* Set scaler function based on Pt */
+  if (cinfo->Al)
+    losslsc->scaler_scale = simple_downscale;
+  else
+    losslsc->scaler_scale = noscale;
+}
+
+
+GLOBAL(void)
+jinit_c_scaler (j_compress_ptr cinfo)
+{
+  j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+
+  losslsc->scaler_start_pass = scaler_start_pass;
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jcshuff.c b/Utilities/ITK/Utilities/itkjpeg/jcshuff.c
new file mode 100644
index 0000000000000000000000000000000000000000..85557158b7f8aaf0c0fd47012f4fc4a8540e372d
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jcshuff.c
@@ -0,0 +1,662 @@
+/*
+ * jcshuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy encoding routines for sequential JPEG.
+ *
+ * Much of the complexity here has to do with supporting output suspension.
+ * If the data destination module demands suspension, we want to be able to
+ * back up to the start of the current MCU.  To do this, we copy state
+ * variables into local working storage, and update them back to the
+ * permanent JPEG objects only upon successful completion of an MCU.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"    /* Private declarations for lossy codec */
+#include "jchuff.h"    /* Declarations shared with jc*huff.c */
+
+
+/* Expanded entropy encoder object for Huffman encoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+  INT32 put_buffer;    /* current bit-accumulation buffer */
+  int put_bits;      /* # of bits now in it */
+  int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment.  You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src)  ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src)  \
+  ((dest).put_buffer = (src).put_buffer, \
+   (dest).put_bits = (src).put_bits, \
+   (dest).last_dc_val[0] = (src).last_dc_val[0], \
+   (dest).last_dc_val[1] = (src).last_dc_val[1], \
+   (dest).last_dc_val[2] = (src).last_dc_val[2], \
+   (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+  savable_state saved;    /* Bit buffer & DC state at start of MCU */
+
+  /* These fields are NOT loaded into local working state. */
+  unsigned int restarts_to_go;  /* MCUs left in this restart interval */
+  int next_restart_num;    /* next restart number to write (0-7) */
+
+  /* Pointers to derived tables (these workspaces have image lifespan) */
+  c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
+  c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
+
+#ifdef ENTROPY_OPT_SUPPORTED  /* Statistics tables for optimization */
+  long * dc_count_ptrs[NUM_HUFF_TBLS];
+  long * ac_count_ptrs[NUM_HUFF_TBLS];
+#endif
+} shuff_entropy_encoder;
+
+typedef shuff_entropy_encoder * shuff_entropy_ptr;
+
+/* Working state while writing an MCU.
+ * This struct contains all the fields that are needed by subroutines.
+ */
+
+typedef struct {
+  JOCTET * next_output_byte;  /* => next byte to write in buffer */
+  size_t free_in_buffer;  /* # of byte spaces remaining in buffer */
+  savable_state cur;    /* Current bit buffer & DC state */
+  j_compress_ptr cinfo;    /* dump_buffer needs access to this */
+} working_state;
+
+
+/* Forward declarations */
+METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo,
+          JBLOCKROW *MCU_data));
+METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo));
+#ifdef ENTROPY_OPT_SUPPORTED
+METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo,
+            JBLOCKROW *MCU_data));
+METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo));
+#endif
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ * If gather_statistics is TRUE, we do not output anything during the scan,
+ * just count the Huffman symbols used and generate Huffman code tables.
+ */
+
+METHODDEF(void)
+start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
+  int ci, dctbl, actbl;
+  jpeg_component_info * compptr;
+
+  if (gather_statistics) {
+#ifdef ENTROPY_OPT_SUPPORTED
+    lossyc->entropy_encode_mcu = encode_mcu_gather;
+    lossyc->pub.entropy_finish_pass = finish_pass_gather;
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+  } else {
+    lossyc->entropy_encode_mcu = encode_mcu_huff;
+    lossyc->pub.entropy_finish_pass = finish_pass_huff;
+  }
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    dctbl = compptr->dc_tbl_no;
+    actbl = compptr->ac_tbl_no;
+    if (gather_statistics) {
+#ifdef ENTROPY_OPT_SUPPORTED
+      /* Check for invalid table indexes */
+      /* (make_c_derived_tbl does this in the other path) */
+      if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS)
+  ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
+      if (actbl < 0 || actbl >= NUM_HUFF_TBLS)
+  ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
+      /* Allocate and zero the statistics tables */
+      /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
+      if (entropy->dc_count_ptrs[dctbl] == NULL)
+  entropy->dc_count_ptrs[dctbl] = (long *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+              257 * SIZEOF(long));
+      MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long));
+      if (entropy->ac_count_ptrs[actbl] == NULL)
+  entropy->ac_count_ptrs[actbl] = (long *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+              257 * SIZEOF(long));
+      MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long));
+#endif
+    } else {
+      /* Compute derived values for Huffman tables */
+      /* We may do this more than once for a table, but it's not expensive */
+      jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
+            & entropy->dc_derived_tbls[dctbl]);
+      jpeg_make_c_derived_tbl(cinfo, FALSE, actbl,
+            & entropy->ac_derived_tbls[actbl]);
+    }
+    /* Initialize DC predictions to 0 */
+    entropy->saved.last_dc_val[ci] = 0;
+  }
+
+  /* Initialize bit buffer to empty */
+  entropy->saved.put_buffer = 0;
+  entropy->saved.put_bits = 0;
+
+  /* Initialize restart stuff */
+  entropy->restarts_to_go = cinfo->restart_interval;
+  entropy->next_restart_num = 0;
+}
+
+
+/* Outputting bytes to the file */
+
+/* Emit a byte, taking 'action' if must suspend. */
+#define emit_byte(state,val,action)  \
+  { *(state)->next_output_byte++ = (JOCTET) (val);  \
+    if (--(state)->free_in_buffer == 0)  \
+      if (! dump_buffer(state))  \
+        { action; } }
+
+
+LOCAL(boolean)
+dump_buffer (working_state * state)
+/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
+{
+  struct jpeg_destination_mgr * dest = state->cinfo->dest;
+
+  if (! (*dest->empty_output_buffer) (state->cinfo))
+    return FALSE;
+  /* After a successful buffer dump, must reset buffer pointers */
+  state->next_output_byte = dest->next_output_byte;
+  state->free_in_buffer = dest->free_in_buffer;
+  return TRUE;
+}
+
+
+/* Outputting bits to the file */
+
+/* Only the right 24 bits of put_buffer are used; the valid bits are
+ * left-justified in this part.  At most 16 bits can be passed to emit_bits
+ * in one call, and we never retain more than 7 bits in put_buffer
+ * between calls, so 24 bits are sufficient.
+ */
+
+INLINE
+LOCAL(boolean)
+emit_bits (working_state * state, unsigned int code, int size)
+/* Emit some bits; return TRUE if successful, FALSE if must suspend */
+{
+  /* This routine is heavily used, so it's worth coding tightly. */
+  register INT32 put_buffer = (INT32) code;
+  register int put_bits = state->cur.put_bits;
+
+  /* if size is 0, caller used an invalid Huffman table entry */
+  if (size == 0)
+    ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE);
+
+  put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+  
+  put_bits += size;    /* new number of bits in buffer */
+  
+  put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+  put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
+  
+  while (put_bits >= 8) {
+    int c = (int) ((put_buffer >> 16) & 0xFF);
+    
+    emit_byte(state, c, return FALSE);
+    if (c == 0xFF) {    /* need to stuff a zero byte? */
+      emit_byte(state, 0, return FALSE);
+    }
+    put_buffer <<= 8;
+    put_bits -= 8;
+  }
+
+  state->cur.put_buffer = put_buffer; /* update state variables */
+  state->cur.put_bits = put_bits;
+
+  return TRUE;
+}
+
+
+LOCAL(boolean)
+flush_bits (working_state * state)
+{
+  if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
+    return FALSE;
+  state->cur.put_buffer = 0;  /* and reset bit-buffer to empty */
+  state->cur.put_bits = 0;
+  return TRUE;
+}
+
+
+/* Encode a single block's worth of coefficients */
+
+LOCAL(boolean)
+encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
+      c_derived_tbl *dctbl, c_derived_tbl *actbl)
+{
+  register int temp, temp2;
+  register int nbits;
+  register int k, r, i;
+  
+  /* Encode the DC coefficient difference per section F.1.2.1 */
+  
+  temp = temp2 = block[0] - last_dc_val;
+
+  if (temp < 0) {
+    temp = -temp;    /* temp is abs value of input */
+    /* For a negative input, want temp2 = bitwise complement of abs(input) */
+    /* This code assumes we are on a two's complement machine */
+    temp2--;
+  }
+  
+  /* Find the number of bits needed for the magnitude of the coefficient */
+  nbits = 0;
+  while (temp) {
+    nbits++;
+    temp >>= 1;
+  }
+  /* Check for out-of-range coefficient values.
+   * Since we're encoding a difference, the range limit is twice as much.
+   */
+  if (nbits > MAX_COEF_BITS+1)
+    ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
+  
+  /* Emit the Huffman-coded symbol for the number of bits */
+  if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
+    return FALSE;
+
+  /* Emit that number of bits of the value, if positive, */
+  /* or the complement of its magnitude, if negative. */
+  if (nbits)      /* emit_bits rejects calls with size 0 */
+    if (! emit_bits(state, (unsigned int) temp2, nbits))
+      return FALSE;
+
+  /* Encode the AC coefficients per section F.1.2.2 */
+  
+  r = 0;      /* r = run length of zeros */
+  
+  for (k = 1; k < DCTSIZE2; k++) {
+    if ((temp = block[jpeg_natural_order[k]]) == 0) {
+      r++;
+    } else {
+      /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+      while (r > 15) {
+  if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
+    return FALSE;
+  r -= 16;
+      }
+
+      temp2 = temp;
+      if (temp < 0) {
+  temp = -temp;    /* temp is abs value of input */
+  /* This code assumes we are on a two's complement machine */
+  temp2--;
+      }
+      
+      /* Find the number of bits needed for the magnitude of the coefficient */
+      nbits = 1;    /* there must be at least one 1 bit */
+      while ((temp >>= 1))
+  nbits++;
+      /* Check for out-of-range coefficient values */
+      if (nbits > MAX_COEF_BITS)
+  ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
+      
+      /* Emit Huffman symbol for run length / number of bits */
+      i = (r << 4) + nbits;
+      if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i]))
+  return FALSE;
+
+      /* Emit that number of bits of the value, if positive, */
+      /* or the complement of its magnitude, if negative. */
+      if (! emit_bits(state, (unsigned int) temp2, nbits))
+  return FALSE;
+      
+      r = 0;
+    }
+  }
+
+  /* If the last coef(s) were zero, emit an end-of-block code */
+  if (r > 0)
+    if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0]))
+      return FALSE;
+
+  return TRUE;
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL(boolean)
+emit_restart (working_state * state, int restart_num)
+{
+  int ci;
+
+  if (! flush_bits(state))
+    return FALSE;
+
+  emit_byte(state, 0xFF, return FALSE);
+  emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
+
+  /* Re-initialize DC predictions to 0 */
+  for (ci = 0; ci < state->cinfo->comps_in_scan; ci++)
+    state->cur.last_dc_val[ci] = 0;
+
+  /* The restart counter is not updated until we successfully write the MCU. */
+
+  return TRUE;
+}
+
+
+/*
+ * Encode and output one MCU's worth of Huffman-compressed coefficients.
+ */
+
+METHODDEF(boolean)
+encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
+  working_state state;
+  int blkn, ci;
+  jpeg_component_info * compptr;
+
+  /* Load up working state */
+  state.next_output_byte = cinfo->dest->next_output_byte;
+  state.free_in_buffer = cinfo->dest->free_in_buffer;
+  ASSIGN_STATE(state.cur, entropy->saved);
+  state.cinfo = cinfo;
+
+  /* Emit restart marker if needed */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0)
+      if (! emit_restart(&state, entropy->next_restart_num))
+  return FALSE;
+  }
+
+  /* Encode the MCU data blocks */
+  for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+    ci = cinfo->MCU_membership[blkn];
+    compptr = cinfo->cur_comp_info[ci];
+    if (! encode_one_block(&state,
+         MCU_data[blkn][0], state.cur.last_dc_val[ci],
+         entropy->dc_derived_tbls[compptr->dc_tbl_no],
+         entropy->ac_derived_tbls[compptr->ac_tbl_no]))
+      return FALSE;
+    /* Update last_dc_val */
+    state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
+  }
+
+  /* Completed MCU, so update state */
+  cinfo->dest->next_output_byte = state.next_output_byte;
+  cinfo->dest->free_in_buffer = state.free_in_buffer;
+  ASSIGN_STATE(entropy->saved, state.cur);
+
+  /* Update restart-interval state too */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0) {
+      entropy->restarts_to_go = cinfo->restart_interval;
+      entropy->next_restart_num++;
+      entropy->next_restart_num &= 7;
+    }
+    entropy->restarts_to_go--;
+  }
+
+  return TRUE;
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+finish_pass_huff (j_compress_ptr cinfo)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
+  working_state state;
+
+  /* Load up working state ... flush_bits needs it */
+  state.next_output_byte = cinfo->dest->next_output_byte;
+  state.free_in_buffer = cinfo->dest->free_in_buffer;
+  ASSIGN_STATE(state.cur, entropy->saved);
+  state.cinfo = cinfo;
+
+  /* Flush out the last data */
+  if (! flush_bits(&state))
+    ERREXIT(cinfo, JERR_CANT_SUSPEND);
+
+  /* Update state */
+  cinfo->dest->next_output_byte = state.next_output_byte;
+  cinfo->dest->free_in_buffer = state.free_in_buffer;
+  ASSIGN_STATE(entropy->saved, state.cur);
+}
+
+
+/*
+ * Huffman coding optimization.
+ *
+ * We first scan the supplied data and count the number of uses of each symbol
+ * that is to be Huffman-coded. (This process MUST agree with the code above.)
+ * Then we build a Huffman coding tree for the observed counts.
+ * Symbols which are not needed at all for the particular image are not
+ * assigned any code, which saves space in the DHT marker as well as in
+ * the compressed data.
+ */
+
+#ifdef ENTROPY_OPT_SUPPORTED
+
+
+/* Process a single block's worth of coefficients */
+
+LOCAL(void)
+htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
+     long dc_counts[], long ac_counts[])
+{
+  register int temp;
+  register int nbits;
+  register int k, r;
+  
+  /* Encode the DC coefficient difference per section F.1.2.1 */
+  
+  temp = block[0] - last_dc_val;
+  if (temp < 0)
+    temp = -temp;
+  
+  /* Find the number of bits needed for the magnitude of the coefficient */
+  nbits = 0;
+  while (temp) {
+    nbits++;
+    temp >>= 1;
+  }
+  /* Check for out-of-range coefficient values.
+   * Since we're encoding a difference, the range limit is twice as much.
+   */
+  if (nbits > MAX_COEF_BITS+1)
+    ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+  /* Count the Huffman symbol for the number of bits */
+  dc_counts[nbits]++;
+  
+  /* Encode the AC coefficients per section F.1.2.2 */
+  
+  r = 0;      /* r = run length of zeros */
+  
+  for (k = 1; k < DCTSIZE2; k++) {
+    if ((temp = block[jpeg_natural_order[k]]) == 0) {
+      r++;
+    } else {
+      /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+      while (r > 15) {
+  ac_counts[0xF0]++;
+  r -= 16;
+      }
+      
+      /* Find the number of bits needed for the magnitude of the coefficient */
+      if (temp < 0)
+  temp = -temp;
+      
+      /* Find the number of bits needed for the magnitude of the coefficient */
+      nbits = 1;    /* there must be at least one 1 bit */
+      while ((temp >>= 1))
+  nbits++;
+      /* Check for out-of-range coefficient values */
+      if (nbits > MAX_COEF_BITS)
+  ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+      
+      /* Count Huffman symbol for run length / number of bits */
+      ac_counts[(r << 4) + nbits]++;
+      
+      r = 0;
+    }
+  }
+
+  /* If the last coef(s) were zero, emit an end-of-block code */
+  if (r > 0)
+    ac_counts[0]++;
+}
+
+
+/*
+ * Trial-encode one MCU's worth of Huffman-compressed coefficients.
+ * No data is actually output, so no suspension return is possible.
+ */
+
+METHODDEF(boolean)
+encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
+  int blkn, ci;
+  jpeg_component_info * compptr;
+
+  /* Take care of restart intervals if needed */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0) {
+      /* Re-initialize DC predictions to 0 */
+      for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+  entropy->saved.last_dc_val[ci] = 0;
+      /* Update restart state */
+      entropy->restarts_to_go = cinfo->restart_interval;
+    }
+    entropy->restarts_to_go--;
+  }
+
+  for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+    ci = cinfo->MCU_membership[blkn];
+    compptr = cinfo->cur_comp_info[ci];
+    htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci],
+        entropy->dc_count_ptrs[compptr->dc_tbl_no],
+        entropy->ac_count_ptrs[compptr->ac_tbl_no]);
+    entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0];
+  }
+
+  return TRUE;
+}
+
+
+/*
+ * Finish up a statistics-gathering pass and create the new Huffman tables.
+ */
+
+METHODDEF(void)
+finish_pass_gather (j_compress_ptr cinfo)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
+  int ci, dctbl, actbl;
+  jpeg_component_info * compptr;
+  JHUFF_TBL **htblptr;
+  boolean did_dc[NUM_HUFF_TBLS];
+  boolean did_ac[NUM_HUFF_TBLS];
+
+  /* It's important not to apply jpeg_gen_optimal_table more than once
+   * per table, because it clobbers the input frequency counts!
+   */
+  MEMZERO(did_dc, SIZEOF(did_dc));
+  MEMZERO(did_ac, SIZEOF(did_ac));
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    dctbl = compptr->dc_tbl_no;
+    actbl = compptr->ac_tbl_no;
+    if (! did_dc[dctbl]) {
+      htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
+      if (*htblptr == NULL)
+  *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+      jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]);
+      did_dc[dctbl] = TRUE;
+    }
+    if (! did_ac[actbl]) {
+      htblptr = & cinfo->ac_huff_tbl_ptrs[actbl];
+      if (*htblptr == NULL)
+  *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+      jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]);
+      did_ac[actbl] = TRUE;
+    }
+  }
+}
+
+
+#endif /* ENTROPY_OPT_SUPPORTED */
+
+
+METHODDEF(boolean)
+need_optimization_pass (j_compress_ptr cinfo)
+{
+  (void)cinfo;
+  return TRUE;
+}
+
+
+/*
+ * Module initialization routine for Huffman entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_shuff_encoder (j_compress_ptr cinfo)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  shuff_entropy_ptr entropy;
+  int i;
+
+  entropy = (shuff_entropy_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(shuff_entropy_encoder));
+  lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy;
+  lossyc->pub.entropy_start_pass = start_pass_huff;
+  lossyc->pub.need_optimization_pass = need_optimization_pass;
+
+  /* Mark tables unallocated */
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
+#ifdef ENTROPY_OPT_SUPPORTED
+    entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL;
+#endif
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jctrans.c b/Utilities/ITK/Utilities/itkjpeg/jctrans.c
new file mode 100644
index 0000000000000000000000000000000000000000..0c94656a68411784d1e076f23056e28514947386
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jctrans.c
@@ -0,0 +1,421 @@
+/*
+ * jctrans.c
+ *
+ * Copyright (C) 1995-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains library routines for transcoding compression,
+ * that is, writing raw DCT coefficient arrays to an output JPEG file.
+ * The routines in jcapimin.c will also be needed by a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"    /* Private declarations for lossy codec */
+
+
+/* Forward declarations */
+LOCAL(void) transencode_master_selection
+  JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
+LOCAL(void) transencode_codec
+  JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
+LOCAL(void) transencode_coef_controller
+  JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
+
+
+/*
+ * Compression initialization for writing raw-coefficient data.
+ * Before calling this, all parameters and a data destination must be set up.
+ * Call jpeg_finish_compress() to actually write the data.
+ *
+ * The number of passed virtual arrays must match cinfo->num_components.
+ * Note that the virtual arrays need not be filled or even realized at
+ * the time write_coefficients is called; indeed, if the virtual arrays
+ * were requested from this compression object's memory manager, they
+ * typically will be realized during this routine and filled afterwards.
+ */
+
+GLOBAL(void)
+jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)
+{
+  if (cinfo->global_state != CSTATE_START)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  /* Mark all tables to be written */
+  jpeg_suppress_tables(cinfo, FALSE);
+  /* (Re)initialize error mgr and destination modules */
+  (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+  (*cinfo->dest->init_destination) (cinfo);
+  /* Perform master selection of active modules */
+  transencode_master_selection(cinfo, coef_arrays);
+  /* Wait for jpeg_finish_compress() call */
+  cinfo->next_scanline = 0;  /* so jpeg_write_marker works */
+  cinfo->global_state = CSTATE_WRCOEFS;
+}
+
+
+/*
+ * Initialize the compression object with default parameters,
+ * then copy from the source object all parameters needed for lossless
+ * transcoding.  Parameters that can be varied without loss (such as
+ * scan script and Huffman optimization) are left in their default states.
+ */
+
+GLOBAL(void)
+jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
+             j_compress_ptr dstinfo)
+{
+  JQUANT_TBL ** qtblptr;
+  jpeg_component_info *incomp, *outcomp;
+  JQUANT_TBL *c_quant, *slot_quant;
+  int tblno, ci, coefi;
+
+  /* Safety check to ensure start_compress not called yet. */
+  if (dstinfo->global_state != CSTATE_START)
+    ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
+  /* Copy fundamental image dimensions */
+  dstinfo->image_width = srcinfo->image_width;
+  dstinfo->image_height = srcinfo->image_height;
+  dstinfo->input_components = srcinfo->num_components;
+  dstinfo->in_color_space = srcinfo->jpeg_color_space;
+  /* Initialize all parameters to default values */
+  jpeg_set_defaults(dstinfo);
+  /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB.
+   * Fix it to get the right header markers for the image colorspace.
+   */
+  jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space);
+  dstinfo->data_precision = srcinfo->data_precision;
+  dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling;
+  /* Copy the source's quantization tables. */
+  for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
+    if (srcinfo->quant_tbl_ptrs[tblno] != NULL) {
+      qtblptr = & dstinfo->quant_tbl_ptrs[tblno];
+      if (*qtblptr == NULL)
+  *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo);
+      MEMCOPY((*qtblptr)->quantval,
+        srcinfo->quant_tbl_ptrs[tblno]->quantval,
+        SIZEOF((*qtblptr)->quantval));
+      (*qtblptr)->sent_table = FALSE;
+    }
+  }
+  /* Copy the source's per-component info.
+   * Note we assume jpeg_set_defaults has allocated the dest comp_info array.
+   */
+  dstinfo->num_components = srcinfo->num_components;
+  if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS)
+    ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components,
+       MAX_COMPONENTS);
+  for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info;
+       ci < dstinfo->num_components; ci++, incomp++, outcomp++) {
+    outcomp->component_id = incomp->component_id;
+    outcomp->h_samp_factor = incomp->h_samp_factor;
+    outcomp->v_samp_factor = incomp->v_samp_factor;
+    outcomp->quant_tbl_no = incomp->quant_tbl_no;
+    /* Make sure saved quantization table for component matches the qtable
+     * slot.  If not, the input file re-used this qtable slot.
+     * IJG encoder currently cannot duplicate this.
+     */
+    tblno = outcomp->quant_tbl_no;
+    if (tblno < 0 || tblno >= NUM_QUANT_TBLS ||
+  srcinfo->quant_tbl_ptrs[tblno] == NULL)
+      ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno);
+    slot_quant = srcinfo->quant_tbl_ptrs[tblno];
+    c_quant = incomp->quant_table;
+    if (c_quant != NULL) {
+      for (coefi = 0; coefi < DCTSIZE2; coefi++) {
+  if (c_quant->quantval[coefi] != slot_quant->quantval[coefi])
+    ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno);
+      }
+    }
+    /* Note: we do not copy the source's Huffman table assignments;
+     * instead we rely on jpeg_set_colorspace to have made a suitable choice.
+     */
+  }
+  /* Also copy JFIF version and resolution information, if available.
+   * Strictly speaking this isn't "critical" info, but it's nearly
+   * always appropriate to copy it if available.  In particular,
+   * if the application chooses to copy JFIF 1.02 extension markers from
+   * the source file, we need to copy the version to make sure we don't
+   * emit a file that has 1.02 extensions but a claimed version of 1.01.
+   * We will *not*, however, copy version info from mislabeled "2.01" files.
+   */
+  if (srcinfo->saw_JFIF_marker) {
+    if (srcinfo->JFIF_major_version == 1) {
+      dstinfo->JFIF_major_version = srcinfo->JFIF_major_version;
+      dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version;
+    }
+    dstinfo->density_unit = srcinfo->density_unit;
+    dstinfo->X_density = srcinfo->X_density;
+    dstinfo->Y_density = srcinfo->Y_density;
+  }
+}
+
+
+/*
+ * Master selection of compression modules for transcoding.
+ * This substitutes for jcinit.c's initialization of the full compressor.
+ */
+
+LOCAL(void)
+transencode_master_selection (j_compress_ptr cinfo,
+            jvirt_barray_ptr * coef_arrays)
+{
+  cinfo->data_unit = DCTSIZE;
+  /* Although we don't actually use input_components for transcoding,
+   * jcmaster.c's initial_setup will complain if input_components is 0.
+   */
+  cinfo->input_components = 1;
+  /* Initialize master control (includes parameter checking/processing) */
+  jinit_c_master_control(cinfo, TRUE /* transcode only */);
+
+  /* We need a special compression codec. */
+  transencode_codec(cinfo, coef_arrays);
+
+  jinit_marker_writer(cinfo);
+
+  /* We can now tell the memory manager to allocate virtual arrays. */
+  (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+  /* Write the datastream header (SOI, JFIF) immediately.
+   * Frame and scan headers are postponed till later.
+   * This lets application insert special markers after the SOI.
+   */
+  (*cinfo->marker->write_file_header) (cinfo);
+}
+
+
+/*
+ * The rest of this file is a special implementation of the coefficient
+ * buffer controller.  This is similar to jccoefct.c, but it handles only
+ * output from presupplied virtual arrays.  Furthermore, we generate any
+ * dummy padding blocks on-the-fly rather than expecting them to be present
+ * in the arrays.
+ */
+
+/* Private buffer controller object */
+
+typedef struct {
+  JDIMENSION iMCU_row_num;  /* iMCU row # within image */
+  JDIMENSION mcu_ctr;    /* counts MCUs processed in current row */
+  int MCU_vert_offset;    /* counts MCU rows within iMCU row */
+  int MCU_rows_per_iMCU_row;  /* number of such rows needed */
+
+  /* Virtual block array for each component. */
+  jvirt_barray_ptr * whole_image;
+
+  /* Workspace for constructing dummy blocks at right/bottom edges. */
+  JBLOCKROW dummy_buffer[C_MAX_DATA_UNITS_IN_MCU];
+} c_coef_controller;
+
+typedef c_coef_controller * c_coef_ptr;
+
+
+LOCAL(void)
+start_iMCU_row (j_compress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row */
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+
+  /* In an interleaved scan, an MCU row is the same as an iMCU row.
+   * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+   * But at the bottom of the image, process only what's left.
+   */
+  if (cinfo->comps_in_scan > 1) {
+    coef->MCU_rows_per_iMCU_row = 1;
+  } else {
+    if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+    else
+      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+  }
+
+  coef->mcu_ctr = 0;
+  coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+
+  if (pass_mode != JBUF_CRANK_DEST)
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+  coef->iMCU_row_num = 0;
+  start_iMCU_row(cinfo);
+}
+
+
+/*
+ * Process some data.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the scan.
+ * The data is obtained from the virtual arrays and fed to the entropy coder.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf is ignored; it is likely to be a NULL pointer.
+ */
+
+METHODDEF(boolean)
+compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+  JDIMENSION MCU_col_num;  /* index of current MCU within row */
+  JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+  int blkn, ci, xindex, yindex, yoffset, blockcnt;
+  JDIMENSION start_col;
+  JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+  JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU];
+  JBLOCKROW buffer_ptr;
+  jpeg_component_info *compptr;
+  (void)input_buf;
+
+  /* Align the virtual buffers for the components used in this scan. */
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    buffer[ci] = (*cinfo->mem->access_virt_barray)
+      ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+       coef->iMCU_row_num * compptr->v_samp_factor,
+       (JDIMENSION) compptr->v_samp_factor, FALSE);
+  }
+
+  /* Loop to process one whole iMCU row */
+  for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+       yoffset++) {
+    for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
+   MCU_col_num++) {
+      /* Construct list of pointers to DCT blocks belonging to this MCU */
+      blkn = 0;      /* index of current DCT block within MCU */
+      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+  compptr = cinfo->cur_comp_info[ci];
+  start_col = MCU_col_num * compptr->MCU_width;
+  blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+            : compptr->last_col_width;
+  for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+    if (coef->iMCU_row_num < last_iMCU_row ||
+        yindex+yoffset < compptr->last_row_height) {
+      /* Fill in pointers to real blocks in this row */
+      buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+      for (xindex = 0; xindex < blockcnt; xindex++)
+        MCU_buffer[blkn++] = buffer_ptr++;
+    } else {
+      /* At bottom of image, need a whole row of dummy blocks */
+      xindex = 0;
+    }
+    /* Fill in any dummy blocks needed in this row.
+     * Dummy blocks are filled in the same way as in jccoefct.c:
+     * all zeroes in the AC entries, DC entries equal to previous
+     * block's DC value.  The init routine has already zeroed the
+     * AC entries, so we need only set the DC entries correctly.
+     */
+    for (; xindex < compptr->MCU_width; xindex++) {
+      MCU_buffer[blkn] = coef->dummy_buffer[blkn];
+      MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0];
+      blkn++;
+    }
+  }
+      }
+      /* Try to write the MCU. */
+      if (! (*lossyc->entropy_encode_mcu) (cinfo, MCU_buffer)) {
+  /* Suspension forced; update state counters and exit */
+  coef->MCU_vert_offset = yoffset;
+  coef->mcu_ctr = MCU_col_num;
+  return FALSE;
+      }
+    }
+    /* Completed an MCU row, but perhaps not an iMCU row */
+    coef->mcu_ctr = 0;
+  }
+  /* Completed the iMCU row, advance counters for next one */
+  coef->iMCU_row_num++;
+  start_iMCU_row(cinfo);
+  return TRUE;
+}
+
+
+/*
+ * Initialize coefficient buffer controller.
+ *
+ * Each passed coefficient array must be the right size for that
+ * coefficient: width_in_data_units wide and height_in_data_units high,
+ * with unitheight at least v_samp_factor.
+ */
+
+LOCAL(void)
+transencode_coef_controller (j_compress_ptr cinfo,
+           jvirt_barray_ptr * coef_arrays)
+{
+  j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+  c_coef_ptr coef;
+  JBLOCKROW buffer;
+  int i;
+
+  coef = (c_coef_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(c_coef_controller));
+  lossyc->coef_private = (struct jpeg_c_coef_controller *) coef;
+
+  /* Save pointer to virtual arrays */
+  coef->whole_image = coef_arrays;
+
+  /* Allocate and pre-zero space for dummy DCT blocks. */
+  buffer = (JBLOCKROW)
+    (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
+  jzero_far((void FAR *) buffer, C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
+  for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) {
+    coef->dummy_buffer[i] = buffer + i;
+  }
+}
+
+
+/*
+ * Initialize the transencoer codec.
+ * This is called only once, during master selection.
+ */
+
+LOCAL(void)
+transencode_codec (j_compress_ptr cinfo,
+       jvirt_barray_ptr * coef_arrays)
+{
+  j_lossy_c_ptr lossyc;
+
+  /* Create subobject in permanent pool */
+  lossyc = (j_lossy_c_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+        SIZEOF(jpeg_lossy_c_codec));
+  cinfo->codec = (struct jpeg_c_codec *) lossyc;
+
+  /* Initialize sub-modules */
+
+  /* Entropy encoding: either Huffman or arithmetic coding. */
+  if (cinfo->arith_code) {
+    jinit_arith_encoder(cinfo);
+  } else {
+    if (cinfo->process == JPROC_PROGRESSIVE) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+      jinit_phuff_encoder(cinfo);
+#else
+      ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+    } else
+      jinit_shuff_encoder(cinfo);
+  }
+
+  /* We need a special coefficient buffer controller. */
+  transencode_coef_controller(cinfo, coef_arrays);
+
+  /* Initialize method pointers */
+  lossyc->pub.start_pass = start_pass_coef;
+  lossyc->pub.compress_data = compress_output;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdapimin.c b/Utilities/ITK/Utilities/itkjpeg/jdapimin.c
new file mode 100644
index 0000000000000000000000000000000000000000..d13a1540ecd425871ea07a6236bc7efa5e5d63bd
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdapimin.c
@@ -0,0 +1,401 @@
+/*
+ * jdapimin.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the decompression half
+ * of the JPEG library.  These are the "minimum" API routines that may be
+ * needed in either the normal full-decompression case or the
+ * transcoding-only case.
+ *
+ * Most of the routines intended to be called directly by an application
+ * are in this file or in jdapistd.c.  But also see jcomapi.c for routines
+ * shared by compression and decompression, and jdtrans.c for the transcoding
+ * case.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Initialization of a JPEG decompression object.
+ * The error manager must already be set up (in case memory manager fails).
+ */
+
+GLOBAL(void)
+jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
+{
+  int i;
+
+  /* Guard against version mismatches between library and caller. */
+  cinfo->mem = NULL;    /* so jpeg_destroy knows mem mgr not called */
+  if (version != JPEG_LIB_VERSION)
+    ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
+  if (structsize != SIZEOF(struct jpeg_decompress_struct))
+    ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE, 
+       (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);
+
+  /* For debugging purposes, we zero the whole master structure.
+   * But the application has already set the err pointer, and may have set
+   * client_data, so we have to save and restore those fields.
+   * Note: if application hasn't set client_data, tools like Purify may
+   * complain here.
+   */
+  {
+    struct jpeg_error_mgr * err = cinfo->err;
+    void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+    MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));
+    cinfo->err = err;
+    cinfo->client_data = client_data;
+  }
+  cinfo->is_decompressor = TRUE;
+
+  /* Initialize a memory manager instance for this object */
+  jinit_memory_mgr((j_common_ptr) cinfo);
+
+  /* Zero out pointers to permanent structures. */
+  cinfo->progress = NULL;
+  cinfo->src = NULL;
+
+  for (i = 0; i < NUM_QUANT_TBLS; i++)
+    cinfo->quant_tbl_ptrs[i] = NULL;
+
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    cinfo->dc_huff_tbl_ptrs[i] = NULL;
+    cinfo->ac_huff_tbl_ptrs[i] = NULL;
+  }
+
+  /* Initialize marker processor so application can override methods
+   * for COM, APPn markers before calling jpeg_read_header.
+   */
+  cinfo->marker_list = NULL;
+  jinit_marker_reader(cinfo);
+
+  /* And initialize the overall input controller. */
+  jinit_input_controller(cinfo);
+
+  /* OK, I'm ready */
+  cinfo->global_state = DSTATE_START;
+}
+
+
+/*
+ * Destruction of a JPEG decompression object
+ */
+
+GLOBAL(void)
+jpeg_destroy_decompress (j_decompress_ptr cinfo)
+{
+  jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Abort processing of a JPEG decompression operation,
+ * but don't destroy the object itself.
+ */
+
+GLOBAL(void)
+jpeg_abort_decompress (j_decompress_ptr cinfo)
+{
+  jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Set default decompression parameters.
+ */
+
+LOCAL(void)
+default_decompress_parms (j_decompress_ptr cinfo)
+{
+  /* Guess the input colorspace, and set output colorspace accordingly. */
+  /* (Wish JPEG committee had provided a real way to specify this...) */
+  /* Note application may override our guesses. */
+  switch (cinfo->num_components) {
+  case 1:
+    cinfo->jpeg_color_space = JCS_GRAYSCALE;
+    cinfo->out_color_space = JCS_GRAYSCALE;
+    break;
+    
+  case 3:
+    if (cinfo->saw_JFIF_marker) {
+      cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
+    } else if (cinfo->saw_Adobe_marker) {
+      switch (cinfo->Adobe_transform) {
+      case 0:
+  cinfo->jpeg_color_space = JCS_RGB;
+  break;
+      case 1:
+  cinfo->jpeg_color_space = JCS_YCbCr;
+  break;
+      default:
+  WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
+  cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+  break;
+      }
+    } else {
+      /* Saw no special markers, try to guess from the component IDs */
+      int cid0 = cinfo->comp_info[0].component_id;
+      int cid1 = cinfo->comp_info[1].component_id;
+      int cid2 = cinfo->comp_info[2].component_id;
+
+      if (cid0 == 1 && cid1 == 2 && cid2 == 3)
+  cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
+      else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
+  cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
+      else {
+  if (cinfo->process == JPROC_LOSSLESS) {
+    TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSLESS_IDS, cid0, cid1, cid2);
+    cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */
+  }
+  else {  /* Lossy processes */
+    TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSY_IDS, cid0, cid1, cid2);
+    cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+  }
+      }
+    }
+    /* Always guess RGB is proper output colorspace. */
+    cinfo->out_color_space = JCS_RGB;
+    break;
+    
+  case 4:
+    if (cinfo->saw_Adobe_marker) {
+      switch (cinfo->Adobe_transform) {
+      case 0:
+  cinfo->jpeg_color_space = JCS_CMYK;
+  break;
+      case 2:
+  cinfo->jpeg_color_space = JCS_YCCK;
+  break;
+      default:
+  WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
+  cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
+  break;
+      }
+    } else {
+      /* No special markers, assume straight CMYK. */
+      cinfo->jpeg_color_space = JCS_CMYK;
+    }
+    cinfo->out_color_space = JCS_CMYK;
+    break;
+    
+  default:
+    cinfo->jpeg_color_space = JCS_UNKNOWN;
+    cinfo->out_color_space = JCS_UNKNOWN;
+    break;
+  }
+
+  /* Set defaults for other decompression parameters. */
+  cinfo->scale_num = 1;    /* 1:1 scaling */
+  cinfo->scale_denom = 1;
+  cinfo->output_gamma = 1.0;
+  cinfo->buffered_image = FALSE;
+  cinfo->raw_data_out = FALSE;
+  cinfo->dct_method = JDCT_DEFAULT;
+  cinfo->do_fancy_upsampling = TRUE;
+  cinfo->do_block_smoothing = TRUE;
+  cinfo->quantize_colors = FALSE;
+  /* We set these in case application only sets quantize_colors. */
+  cinfo->dither_mode = JDITHER_FS;
+#ifdef QUANT_2PASS_SUPPORTED
+  cinfo->two_pass_quantize = TRUE;
+#else
+  cinfo->two_pass_quantize = FALSE;
+#endif
+  cinfo->desired_number_of_colors = 256;
+  cinfo->colormap = NULL;
+  /* Initialize for no mode change in buffered-image mode. */
+  cinfo->enable_1pass_quant = FALSE;
+  cinfo->enable_external_quant = FALSE;
+  cinfo->enable_2pass_quant = FALSE;
+}
+
+
+/*
+ * Decompression startup: read start of JPEG datastream to see what's there.
+ * Need only initialize JPEG object and supply a data source before calling.
+ *
+ * This routine will read as far as the first SOS marker (ie, actual start of
+ * compressed data), and will save all tables and parameters in the JPEG
+ * object.  It will also initialize the decompression parameters to default
+ * values, and finally return JPEG_HEADER_OK.  On return, the application may
+ * adjust the decompression parameters and then call jpeg_start_decompress.
+ * (Or, if the application only wanted to determine the image parameters,
+ * the data need not be decompressed.  In that case, call jpeg_abort or
+ * jpeg_destroy to release any temporary space.)
+ * If an abbreviated (tables only) datastream is presented, the routine will
+ * return JPEG_HEADER_TABLES_ONLY upon reaching EOI.  The application may then
+ * re-use the JPEG object to read the abbreviated image datastream(s).
+ * It is unnecessary (but OK) to call jpeg_abort in this case.
+ * The JPEG_SUSPENDED return code only occurs if the data source module
+ * requests suspension of the decompressor.  In this case the application
+ * should load more source data and then re-call jpeg_read_header to resume
+ * processing.
+ * If a non-suspending data source is used and require_image is TRUE, then the
+ * return code need not be inspected since only JPEG_HEADER_OK is possible.
+ *
+ * This routine is now just a front end to jpeg_consume_input, with some
+ * extra error checking.
+ */
+
+GLOBAL(int)
+jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
+{
+  int retcode;
+
+  if (cinfo->global_state != DSTATE_START &&
+      cinfo->global_state != DSTATE_INHEADER)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  retcode = jpeg_consume_input(cinfo);
+
+  switch (retcode) {
+  case JPEG_REACHED_SOS:
+    retcode = JPEG_HEADER_OK;
+    break;
+  case JPEG_REACHED_EOI:
+    if (require_image)    /* Complain if application wanted an image */
+      ERREXIT(cinfo, JERR_NO_IMAGE);
+    /* Reset to start state; it would be safer to require the application to
+     * call jpeg_abort, but we can't change it now for compatibility reasons.
+     * A side effect is to free any temporary memory (there shouldn't be any).
+     */
+    jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
+    retcode = JPEG_HEADER_TABLES_ONLY;
+    break;
+  case JPEG_SUSPENDED:
+    /* no work */
+    break;
+  }
+
+  return retcode;
+}
+
+
+/*
+ * Consume data in advance of what the decompressor requires.
+ * This can be called at any time once the decompressor object has
+ * been created and a data source has been set up.
+ *
+ * This routine is essentially a state machine that handles a couple
+ * of critical state-transition actions, namely initial setup and
+ * transition from header scanning to ready-for-start_decompress.
+ * All the actual input is done via the input controller's consume_input
+ * method.
+ */
+
+GLOBAL(int)
+jpeg_consume_input (j_decompress_ptr cinfo)
+{
+  int retcode = JPEG_SUSPENDED;
+
+  /* NB: every possible DSTATE value should be listed in this switch */
+  switch (cinfo->global_state) {
+  case DSTATE_START:
+    /* Start-of-datastream actions: reset appropriate modules */
+    (*cinfo->inputctl->reset_input_controller) (cinfo);
+    /* Initialize application's data source module */
+    (*cinfo->src->init_source) (cinfo);
+    cinfo->global_state = DSTATE_INHEADER;
+    /*FALLTHROUGH*/
+  case DSTATE_INHEADER:
+    retcode = (*cinfo->inputctl->consume_input) (cinfo);
+    if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
+      /* Set up default parameters based on header data */
+      default_decompress_parms(cinfo);
+      /* Set global state: ready for start_decompress */
+      cinfo->global_state = DSTATE_READY;
+    }
+    break;
+  case DSTATE_READY:
+    /* Can't advance past first SOS until start_decompress is called */
+    retcode = JPEG_REACHED_SOS;
+    break;
+  case DSTATE_PRELOAD:
+  case DSTATE_PRESCAN:
+  case DSTATE_SCANNING:
+  case DSTATE_RAW_OK:
+  case DSTATE_BUFIMAGE:
+  case DSTATE_BUFPOST:
+  case DSTATE_STOPPING:
+    retcode = (*cinfo->inputctl->consume_input) (cinfo);
+    break;
+  default:
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  }
+  return retcode;
+}
+
+
+/*
+ * Have we finished reading the input file?
+ */
+
+GLOBAL(boolean)
+jpeg_input_complete (j_decompress_ptr cinfo)
+{
+  /* Check for valid jpeg object */
+  if (cinfo->global_state < DSTATE_START ||
+      cinfo->global_state > DSTATE_STOPPING)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  return cinfo->inputctl->eoi_reached;
+}
+
+
+/*
+ * Is there more than one scan?
+ */
+
+GLOBAL(boolean)
+jpeg_has_multiple_scans (j_decompress_ptr cinfo)
+{
+  /* Only valid after jpeg_read_header completes */
+  if (cinfo->global_state < DSTATE_READY ||
+      cinfo->global_state > DSTATE_STOPPING)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  return cinfo->inputctl->has_multiple_scans;
+}
+
+
+/*
+ * Finish JPEG decompression.
+ *
+ * This will normally just verify the file trailer and release temp storage.
+ *
+ * Returns FALSE if suspended.  The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_finish_decompress (j_decompress_ptr cinfo)
+{
+  if ((cinfo->global_state == DSTATE_SCANNING ||
+       cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
+    /* Terminate final pass of non-buffered mode */
+    if (cinfo->output_scanline < cinfo->output_height)
+      ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
+    (*cinfo->master->finish_output_pass) (cinfo);
+    cinfo->global_state = DSTATE_STOPPING;
+  } else if (cinfo->global_state == DSTATE_BUFIMAGE) {
+    /* Finishing after a buffered-image operation */
+    cinfo->global_state = DSTATE_STOPPING;
+  } else if (cinfo->global_state != DSTATE_STOPPING) {
+    /* STOPPING = repeat call after a suspension, anything else is error */
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  }
+  /* Read until EOI */
+  while (! cinfo->inputctl->eoi_reached) {
+    if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
+      return FALSE;    /* Suspend, come back later */
+  }
+  /* Do final cleanup */
+  (*cinfo->src->term_source) (cinfo);
+  /* We can use jpeg_abort to release memory and reset global_state */
+  jpeg_abort((j_common_ptr) cinfo);
+  return TRUE;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdapistd.c b/Utilities/ITK/Utilities/itkjpeg/jdapistd.c
new file mode 100644
index 0000000000000000000000000000000000000000..4cc36d719cc18cf9eb85b5d354cfd0d81207c400
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdapistd.c
@@ -0,0 +1,275 @@
+/*
+ * jdapistd.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the decompression half
+ * of the JPEG library.  These are the "standard" API routines that are
+ * used in the normal full-decompression case.  They are not used by a
+ * transcoding-only application.  Note that if an application links in
+ * jpeg_start_decompress, it will end up linking in the entire decompressor.
+ * We thus must separate this file from jdapimin.c to avoid linking the
+ * whole decompression library into a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Forward declarations */
+LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Decompression initialization.
+ * jpeg_read_header must be completed before calling this.
+ *
+ * If a multipass operating mode was selected, this will do all but the
+ * last pass, and thus may take a great deal of time.
+ *
+ * Returns FALSE if suspended.  The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_start_decompress (j_decompress_ptr cinfo)
+{
+  if (cinfo->global_state == DSTATE_READY) {
+    /* First call: initialize master control, select active modules */
+    jinit_master_decompress(cinfo);
+    if (cinfo->buffered_image) {
+      /* No more work here; expecting jpeg_start_output next */
+      cinfo->global_state = DSTATE_BUFIMAGE;
+      return TRUE;
+    }
+    cinfo->global_state = DSTATE_PRELOAD;
+  }
+  if (cinfo->global_state == DSTATE_PRELOAD) {
+    /* If file has multiple scans, absorb them all into the coef buffer */
+    if (cinfo->inputctl->has_multiple_scans) {
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+      for (;;) {
+  int retcode;
+  /* Call progress monitor hook if present */
+  if (cinfo->progress != NULL)
+    (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+  /* Absorb some more input */
+  retcode = (*cinfo->inputctl->consume_input) (cinfo);
+  if (retcode == JPEG_SUSPENDED)
+    return FALSE;
+  if (retcode == JPEG_REACHED_EOI)
+    break;
+  /* Advance progress counter if appropriate */
+  if (cinfo->progress != NULL &&
+      (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
+    if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
+      /* jdmaster underestimated number of scans; ratchet up one scan */
+      cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+    }
+  }
+      }
+#else
+      ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+    }
+    cinfo->output_scan_number = cinfo->input_scan_number;
+  } else if (cinfo->global_state != DSTATE_PRESCAN)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  /* Perform any dummy output passes, and set up for the final pass */
+  return output_pass_setup(cinfo);
+}
+
+
+/*
+ * Set up for an output pass, and perform any dummy pass(es) needed.
+ * Common subroutine for jpeg_start_decompress and jpeg_start_output.
+ * Entry: global_state = DSTATE_PRESCAN only if previously suspended.
+ * Exit: If done, returns TRUE and sets global_state for proper output mode.
+ *       If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.
+ */
+
+LOCAL(boolean)
+output_pass_setup (j_decompress_ptr cinfo)
+{
+  if (cinfo->global_state != DSTATE_PRESCAN) {
+    /* First call: do pass setup */
+    (*cinfo->master->prepare_for_output_pass) (cinfo);
+    cinfo->output_scanline = 0;
+    cinfo->global_state = DSTATE_PRESCAN;
+  }
+  /* Loop over any required dummy passes */
+  while (cinfo->master->is_dummy_pass) {
+#ifdef QUANT_2PASS_SUPPORTED
+    /* Crank through the dummy pass */
+    while (cinfo->output_scanline < cinfo->output_height) {
+      JDIMENSION last_scanline;
+      /* Call progress monitor hook if present */
+      if (cinfo->progress != NULL) {
+  cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+  cinfo->progress->pass_limit = (long) cinfo->output_height;
+  (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+      }
+      /* Process some data */
+      last_scanline = cinfo->output_scanline;
+      (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
+            &cinfo->output_scanline, (JDIMENSION) 0);
+      if (cinfo->output_scanline == last_scanline)
+  return FALSE;    /* No progress made, must suspend */
+    }
+    /* Finish up dummy pass, and set up for another one */
+    (*cinfo->master->finish_output_pass) (cinfo);
+    (*cinfo->master->prepare_for_output_pass) (cinfo);
+    cinfo->output_scanline = 0;
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* QUANT_2PASS_SUPPORTED */
+  }
+  /* Ready for application to drive output pass through
+   * jpeg_read_scanlines or jpeg_read_raw_data.
+   */
+  cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
+  return TRUE;
+}
+
+
+/*
+ * Read some scanlines of data from the JPEG decompressor.
+ *
+ * The return value will be the number of lines actually read.
+ * This may be less than the number requested in several cases,
+ * including bottom of image, data source suspension, and operating
+ * modes that emit multiple scanlines at a time.
+ *
+ * Note: we warn about excess calls to jpeg_read_scanlines() since
+ * this likely signals an application programmer error.  However,
+ * an oversize buffer (max_lines > scanlines remaining) is not an error.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
+         JDIMENSION max_lines)
+{
+  JDIMENSION row_ctr;
+
+  if (cinfo->global_state != DSTATE_SCANNING)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  if (cinfo->output_scanline >= cinfo->output_height) {
+    WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+    return 0;
+  }
+
+  /* Call progress monitor hook if present */
+  if (cinfo->progress != NULL) {
+    cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+    cinfo->progress->pass_limit = (long) cinfo->output_height;
+    (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+  }
+
+  /* Process some data */
+  row_ctr = 0;
+  (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
+  cinfo->output_scanline += row_ctr;
+  return row_ctr;
+}
+
+
+/*
+ * Alternate entry point to read raw data.
+ * Processes exactly one iMCU row per call, unless suspended.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
+        JDIMENSION max_lines)
+{
+  JDIMENSION lines_per_iMCU_row;
+
+  if (cinfo->global_state != DSTATE_RAW_OK)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  if (cinfo->output_scanline >= cinfo->output_height) {
+    WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+    return 0;
+  }
+
+  /* Call progress monitor hook if present */
+  if (cinfo->progress != NULL) {
+    cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+    cinfo->progress->pass_limit = (long) cinfo->output_height;
+    (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+  }
+
+  /* Verify that at least one iMCU row can be returned. */
+  lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_codec_data_unit;
+  if (max_lines < lines_per_iMCU_row)
+    ERREXIT(cinfo, JERR_BUFFER_SIZE);
+
+  /* Decompress directly into user's buffer. */
+  if (! (*cinfo->codec->decompress_data) (cinfo, data))
+    return 0;      /* suspension forced, can do nothing more */
+
+  /* OK, we processed one iMCU row. */
+  cinfo->output_scanline += lines_per_iMCU_row;
+  return lines_per_iMCU_row;
+}
+
+
+/* Additional entry points for buffered-image mode. */
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Initialize for an output pass in buffered-image mode.
+ */
+
+GLOBAL(boolean)
+jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
+{
+  if (cinfo->global_state != DSTATE_BUFIMAGE &&
+      cinfo->global_state != DSTATE_PRESCAN)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  /* Limit scan number to valid range */
+  if (scan_number <= 0)
+    scan_number = 1;
+  if (cinfo->inputctl->eoi_reached &&
+      scan_number > cinfo->input_scan_number)
+    scan_number = cinfo->input_scan_number;
+  cinfo->output_scan_number = scan_number;
+  /* Perform any dummy output passes, and set up for the real pass */
+  return output_pass_setup(cinfo);
+}
+
+
+/*
+ * Finish up after an output pass in buffered-image mode.
+ *
+ * Returns FALSE if suspended.  The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_finish_output (j_decompress_ptr cinfo)
+{
+  if ((cinfo->global_state == DSTATE_SCANNING ||
+       cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
+    /* Terminate this pass. */
+    /* We do not require the whole pass to have been completed. */
+    (*cinfo->master->finish_output_pass) (cinfo);
+    cinfo->global_state = DSTATE_BUFPOST;
+  } else if (cinfo->global_state != DSTATE_BUFPOST) {
+    /* BUFPOST = repeat call after a suspension, anything else is error */
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  }
+  /* Read markers looking for SOS or EOI */
+  while (cinfo->input_scan_number <= cinfo->output_scan_number &&
+   ! cinfo->inputctl->eoi_reached) {
+    if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
+      return FALSE;    /* Suspend, come back later */
+  }
+  cinfo->global_state = DSTATE_BUFIMAGE;
+  return TRUE;
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdarith.c b/Utilities/ITK/Utilities/itkjpeg/jdarith.c
new file mode 100644
index 0000000000000000000000000000000000000000..52eb79d7af0b32eb23e7f9fb56cffe644bd082ed
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdarith.c
@@ -0,0 +1,24 @@
+/*
+ * jdarith.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file holds place for arithmetic entropy decoding routines.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Module initialization routine for arithmetic entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_arith_decoder (j_decompress_ptr cinfo)
+{
+  ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdatadst.c b/Utilities/ITK/Utilities/itkjpeg/jdatadst.c
new file mode 100644
index 0000000000000000000000000000000000000000..88d859d210238daa04e630429f2c918513743854
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdatadst.c
@@ -0,0 +1,151 @@
+/*
+ * jdatadst.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains compression data destination routines for the case of
+ * emitting JPEG data to a file (or any stdio stream).  While these routines
+ * are sufficient for most applications, some will want to use a different
+ * destination manager.
+ * IMPORTANT: we assume that fwrite() will correctly transcribe an array of
+ * JOCTETs into 8-bit-wide elements on external storage.  If char is wider
+ * than 8 bits on your machine, you may need to do some tweaking.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jerror.h"
+
+
+/* Expanded data destination object for stdio output */
+
+typedef struct {
+  struct jpeg_destination_mgr pub; /* public fields */
+
+  FILE * outfile;    /* target stream */
+  JOCTET * buffer;    /* start of buffer */
+} my_destination_mgr;
+
+typedef my_destination_mgr * my_dest_ptr;
+
+#define OUTPUT_BUF_SIZE  4096  /* choose an efficiently fwrite'able size */
+
+
+/*
+ * Initialize destination --- called by jpeg_start_compress
+ * before any data is actually written.
+ */
+
+METHODDEF(void)
+init_destination (j_compress_ptr cinfo)
+{
+  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+  /* Allocate the output buffer --- it will be released when done with image */
+  dest->buffer = (JOCTET *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
+
+  dest->pub.next_output_byte = dest->buffer;
+  dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+
+/*
+ * Empty the output buffer --- called whenever buffer fills up.
+ *
+ * In typical applications, this should write the entire output buffer
+ * (ignoring the current state of next_output_byte & free_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been dumped.
+ *
+ * In applications that need to be able to suspend compression due to output
+ * overrun, a FALSE return indicates that the buffer cannot be emptied now.
+ * In this situation, the compressor will return to its caller (possibly with
+ * an indication that it has not accepted all the supplied scanlines).  The
+ * application should resume compression after it has made more room in the
+ * output buffer.  Note that there are substantial restrictions on the use of
+ * suspension --- see the documentation.
+ *
+ * When suspending, the compressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_output_byte & free_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point will be regenerated after resumption, so do not
+ * write it out when emptying the buffer externally.
+ */
+
+METHODDEF(boolean)
+empty_output_buffer (j_compress_ptr cinfo)
+{
+  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+  if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
+      (size_t) OUTPUT_BUF_SIZE)
+    ERREXIT(cinfo, JERR_FILE_WRITE);
+
+  dest->pub.next_output_byte = dest->buffer;
+  dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+
+  return TRUE;
+}
+
+
+/*
+ * Terminate destination --- called by jpeg_finish_compress
+ * after all data has been written.  Usually needs to flush buffer.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+
+METHODDEF(void)
+term_destination (j_compress_ptr cinfo)
+{
+  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+  size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+
+  /* Write any data remaining in the buffer */
+  if (datacount > 0) {
+    if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
+      ERREXIT(cinfo, JERR_FILE_WRITE);
+  }
+  fflush(dest->outfile);
+  /* Make sure we wrote the output file OK */
+  if (ferror(dest->outfile))
+    ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * Prepare for output to a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing compression.
+ */
+
+GLOBAL(void)
+jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile)
+{
+  my_dest_ptr dest;
+
+  /* The destination object is made permanent so that multiple JPEG images
+   * can be written to the same file without re-executing jpeg_stdio_dest.
+   * This makes it dangerous to use this manager and a different destination
+   * manager serially with the same JPEG object, because their private object
+   * sizes may be different.  Caveat programmer.
+   */
+  if (cinfo->dest == NULL) {  /* first time for this JPEG object? */
+    cinfo->dest = (struct jpeg_destination_mgr *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+          SIZEOF(my_destination_mgr));
+  }
+
+  dest = (my_dest_ptr) cinfo->dest;
+  dest->pub.init_destination = init_destination;
+  dest->pub.empty_output_buffer = empty_output_buffer;
+  dest->pub.term_destination = term_destination;
+  dest->outfile = outfile;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdatasrc.c b/Utilities/ITK/Utilities/itkjpeg/jdatasrc.c
new file mode 100644
index 0000000000000000000000000000000000000000..531c90b34ee996f63fee1ab817efdbf47b4d45d5
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdatasrc.c
@@ -0,0 +1,213 @@
+/*
+ * jdatasrc.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains decompression data source routines for the case of
+ * reading JPEG data from a file (or any stdio stream).  While these routines
+ * are sufficient for most applications, some will want to use a different
+ * source manager.
+ * IMPORTANT: we assume that fread() will correctly transcribe an array of
+ * JOCTETs from 8-bit-wide elements on external storage.  If char is wider
+ * than 8 bits on your machine, you may need to do some tweaking.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jerror.h"
+
+
+/* Expanded data source object for stdio input */
+
+typedef struct {
+  struct jpeg_source_mgr pub;  /* public fields */
+
+  FILE * infile;    /* source stream */
+  JOCTET * buffer;    /* start of buffer */
+  boolean start_of_file;  /* have we gotten any data yet? */
+} my_source_mgr;
+
+typedef my_source_mgr * my_src_ptr;
+
+#define INPUT_BUF_SIZE  4096  /* choose an efficiently fread'able size */
+
+
+/*
+ * Initialize source --- called by jpeg_read_header
+ * before any data is actually read.
+ */
+
+METHODDEF(void)
+init_source (j_decompress_ptr cinfo)
+{
+  my_src_ptr src = (my_src_ptr) cinfo->src;
+
+  /* We reset the empty-input-file flag for each image,
+   * but we don't clear the input buffer.
+   * This is correct behavior for reading a series of images from one source.
+   */
+  src->start_of_file = TRUE;
+}
+
+
+/*
+ * Fill the input buffer --- called whenever buffer is emptied.
+ *
+ * In typical applications, this should read fresh data into the buffer
+ * (ignoring the current state of next_input_byte & bytes_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been reloaded.  It is not necessary to
+ * fill the buffer entirely, only to obtain at least one more byte.
+ *
+ * There is no such thing as an EOF return.  If the end of the file has been
+ * reached, the routine has a choice of ERREXIT() or inserting fake data into
+ * the buffer.  In most cases, generating a warning message and inserting a
+ * fake EOI marker is the best course of action --- this will allow the
+ * decompressor to output however much of the image is there.  However,
+ * the resulting error message is misleading if the real problem is an empty
+ * input file, so we handle that case specially.
+ *
+ * In applications that need to be able to suspend compression due to input
+ * not being available yet, a FALSE return indicates that no more data can be
+ * obtained right now, but more may be forthcoming later.  In this situation,
+ * the decompressor will return to its caller (with an indication of the
+ * number of scanlines it has read, if any).  The application should resume
+ * decompression after it has loaded more data into the input buffer.  Note
+ * that there are substantial restrictions on the use of suspension --- see
+ * the documentation.
+ *
+ * When suspending, the decompressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point must be rescanned after resumption, so move it to
+ * the front of the buffer rather than discarding it.
+ */
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+  my_src_ptr src = (my_src_ptr) cinfo->src;
+  size_t nbytes;
+
+  nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
+
+  if (nbytes <= 0) {
+    if (src->start_of_file)  /* Treat empty input file as fatal error */
+      ERREXIT(cinfo, JERR_INPUT_EMPTY);
+    WARNMS(cinfo, JWRN_JPEG_EOF);
+    /* Insert a fake EOI marker */
+    src->buffer[0] = (JOCTET) 0xFF;
+    src->buffer[1] = (JOCTET) JPEG_EOI;
+    nbytes = 2;
+  }
+
+  src->pub.next_input_byte = src->buffer;
+  src->pub.bytes_in_buffer = nbytes;
+  src->start_of_file = FALSE;
+
+  return TRUE;
+}
+
+
+/*
+ * Skip data --- used to skip over a potentially large amount of
+ * uninteresting data (such as an APPn marker).
+ *
+ * Writers of suspendable-input applications must note that skip_input_data
+ * is not granted the right to give a suspension return.  If the skip extends
+ * beyond the data currently in the buffer, the buffer can be marked empty so
+ * that the next read will cause a fill_input_buffer call that can suspend.
+ * Arranging for additional bytes to be discarded before reloading the input
+ * buffer is the application writer's problem.
+ */
+
+METHODDEF(void)
+skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+  my_src_ptr src = (my_src_ptr) cinfo->src;
+
+  /* Just a dumb implementation for now.  Could use fseek() except
+   * it doesn't work on pipes.  Not clear that being smart is worth
+   * any trouble anyway --- large skips are infrequent.
+   */
+  if (num_bytes > 0) {
+    while (num_bytes > (long) src->pub.bytes_in_buffer) {
+      num_bytes -= (long) src->pub.bytes_in_buffer;
+      (void) fill_input_buffer(cinfo);
+      /* note we assume that fill_input_buffer will never return FALSE,
+       * so suspension need not be handled.
+       */
+    }
+    src->pub.next_input_byte += (size_t) num_bytes;
+    src->pub.bytes_in_buffer -= (size_t) num_bytes;
+  }
+}
+
+
+/*
+ * An additional method that can be provided by data source modules is the
+ * resync_to_restart method for error recovery in the presence of RST markers.
+ * For the moment, this source module just uses the default resync method
+ * provided by the JPEG library.  That method assumes that no backtracking
+ * is possible.
+ */
+
+
+/*
+ * Terminate source --- called by jpeg_finish_decompress
+ * after all data has been read.  Often a no-op.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+
+METHODDEF(void)
+term_source (j_decompress_ptr cinfo)
+{
+  (void)cinfo;
+  /* no work necessary here */
+}
+
+
+/*
+ * Prepare for input from a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing decompression.
+ */
+
+GLOBAL(void)
+jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
+{
+  my_src_ptr src;
+
+  /* The source object and input buffer are made permanent so that a series
+   * of JPEG images can be read from the same file by calling jpeg_stdio_src
+   * only before the first one.  (If we discarded the buffer at the end of
+   * one image, we'd likely lose the start of the next one.)
+   * This makes it unsafe to use this manager and a different source
+   * manager serially with the same JPEG object.  Caveat programmer.
+   */
+  if (cinfo->src == NULL) {  /* first time for this JPEG object? */
+    cinfo->src = (struct jpeg_source_mgr *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+          SIZEOF(my_source_mgr));
+    src = (my_src_ptr) cinfo->src;
+    src->buffer = (JOCTET *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+          INPUT_BUF_SIZE * SIZEOF(JOCTET));
+  }
+
+  src = (my_src_ptr) cinfo->src;
+  src->pub.init_source = init_source;
+  src->pub.fill_input_buffer = fill_input_buffer;
+  src->pub.skip_input_data = skip_input_data;
+  src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+  src->pub.term_source = term_source;
+  src->infile = infile;
+  src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+  src->pub.next_input_byte = NULL; /* until buffer loaded */
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdcoefct.c b/Utilities/ITK/Utilities/itkjpeg/jdcoefct.c
new file mode 100644
index 0000000000000000000000000000000000000000..2e5ec1100c0d3a3fa8a9b6aa927078a20fbd5671
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdcoefct.c
@@ -0,0 +1,744 @@
+/*
+ * jdcoefct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the coefficient buffer controller for decompression.
+ * This controller is the top level of the lossy JPEG decompressor proper.
+ * The coefficient buffer lies between entropy decoding and inverse-DCT steps.
+ *
+ * In buffered-image mode, this controller is the interface between
+ * input-oriented processing and output-oriented processing.
+ * Also, the input side (only) is used when reading a file for transcoding.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"
+
+/* Block smoothing is only applicable for progressive JPEG, so: */
+#ifndef D_PROGRESSIVE_SUPPORTED
+#undef BLOCK_SMOOTHING_SUPPORTED
+#endif
+
+/* Private buffer controller object */
+
+typedef struct {
+  /* These variables keep track of the current location of the input side. */
+  /* cinfo->input_iMCU_row is also used for this. */
+  JDIMENSION MCU_ctr;    /* counts MCUs processed in current row */
+  int MCU_vert_offset;    /* counts MCU rows within iMCU row */
+  int MCU_rows_per_iMCU_row;  /* number of such rows needed */
+
+  /* The output side's location is represented by cinfo->output_iMCU_row. */
+
+  /* In single-pass modes, it's sufficient to buffer just one MCU.
+   * We allocate a workspace of D_MAX_DATA_UNITS_IN_MCU coefficient blocks,
+   * and let the entropy decoder write into that workspace each time.
+   * (On 80x86, the workspace is FAR even though it's not really very big;
+   * this is to keep the module interfaces unchanged when a large coefficient
+   * buffer is necessary.)
+   * In multi-pass modes, this array points to the current MCU's blocks
+   * within the virtual arrays; it is used only by the input side.
+   */
+  JBLOCKROW MCU_buffer[D_MAX_DATA_UNITS_IN_MCU];
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+  /* In multi-pass modes, we need a virtual block array for each component. */
+  jvirt_barray_ptr whole_image[MAX_COMPONENTS];
+#endif
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  /* When doing block smoothing, we latch coefficient Al values here */
+  int * coef_bits_latch;
+#define SAVED_COEFS  6    /* we save coef_bits[0..5] */
+#endif
+} d_coef_controller;
+
+typedef d_coef_controller * d_coef_ptr;
+
+/* Forward declarations */
+METHODDEF(int) decompress_onepass
+  JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+METHODDEF(int) decompress_data
+  JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#endif
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo));
+METHODDEF(int) decompress_smooth_data
+  JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_decompress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row (input side) */
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+
+  /* In an interleaved scan, an MCU row is the same as an iMCU row.
+   * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+   * But at the bottom of the image, process only what's left.
+   */
+  if (cinfo->comps_in_scan > 1) {
+    coef->MCU_rows_per_iMCU_row = 1;
+  } else {
+    if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
+      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+    else
+      coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+  }
+
+  coef->MCU_ctr = 0;
+  coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+  cinfo->input_iMCU_row = 0;
+  start_iMCU_row(cinfo);
+}
+
+
+/*
+ * Initialize for an output processing pass.
+ */
+
+METHODDEF(void)
+start_output_pass (j_decompress_ptr cinfo)
+{
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  /* d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private; */
+
+  /* If multipass, check to see whether to use block smoothing on this pass */
+  if (lossyd->coef_arrays != NULL) {
+    if (cinfo->do_block_smoothing && smoothing_ok(cinfo))
+      lossyd->pub.decompress_data = decompress_smooth_data;
+    else
+      lossyd->pub.decompress_data = decompress_data;
+  }
+#endif
+  cinfo->output_iMCU_row = 0;
+}
+
+
+/*
+ * Decompress and return some data in the single-pass case.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Input and output must run in lockstep since we have only a one-MCU buffer.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(int)
+decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+  JDIMENSION MCU_col_num;  /* index of current MCU within row */
+  JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+  int blkn, ci, xindex, yindex, yoffset, useful_width;
+  JSAMPARRAY output_ptr;
+  JDIMENSION start_col, output_col;
+  jpeg_component_info *compptr;
+  inverse_DCT_method_ptr inverse_DCT;
+
+  /* Loop to process as much as one whole iMCU row */
+  for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+       yoffset++) {
+    for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
+   MCU_col_num++) {
+      /* Try to fetch an MCU.  Entropy decoder expects buffer to be zeroed. */
+      jzero_far((void FAR *) coef->MCU_buffer[0],
+    (size_t) (cinfo->data_units_in_MCU * SIZEOF(JBLOCK)));
+      if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) {
+  /* Suspension forced; update state counters and exit */
+  coef->MCU_vert_offset = yoffset;
+  coef->MCU_ctr = MCU_col_num;
+  return JPEG_SUSPENDED;
+      }
+      /* Determine where data should go in output_buf and do the IDCT thing.
+       * We skip dummy blocks at the right and bottom edges (but blkn gets
+       * incremented past them!).  Note the inner loop relies on having
+       * allocated the MCU_buffer[] blocks sequentially.
+       */
+      blkn = 0;      /* index of current DCT block within MCU */
+      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+  compptr = cinfo->cur_comp_info[ci];
+  /* Don't bother to IDCT an uninteresting component. */
+  if (! compptr->component_needed) {
+    blkn += compptr->MCU_data_units;
+    continue;
+  }
+  inverse_DCT = lossyd->inverse_DCT[compptr->component_index];
+  useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+                : compptr->last_col_width;
+  output_ptr = output_buf[compptr->component_index] +
+    yoffset * compptr->codec_data_unit;
+  start_col = MCU_col_num * compptr->MCU_sample_width;
+  for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+    if (cinfo->input_iMCU_row < last_iMCU_row ||
+        yoffset+yindex < compptr->last_row_height) {
+      output_col = start_col;
+      for (xindex = 0; xindex < useful_width; xindex++) {
+        (*inverse_DCT) (cinfo, compptr,
+            (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
+            output_ptr, output_col);
+        output_col += compptr->codec_data_unit;
+      }
+    }
+    blkn += compptr->MCU_width;
+    output_ptr += compptr->codec_data_unit;
+  }
+      }
+    }
+    /* Completed an MCU row, but perhaps not an iMCU row */
+    coef->MCU_ctr = 0;
+  }
+  /* Completed the iMCU row, advance counters for next one */
+  cinfo->output_iMCU_row++;
+  if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
+    start_iMCU_row(cinfo);
+    return JPEG_ROW_COMPLETED;
+  }
+  /* Completed the scan */
+  (*cinfo->inputctl->finish_input_pass) (cinfo);
+  return JPEG_SCAN_COMPLETED;
+}
+
+
+/*
+ * Dummy consume-input routine for single-pass operation.
+ */
+
+METHODDEF(int)
+dummy_consume_data (j_decompress_ptr cinfo)
+{
+  (void)cinfo;
+  return JPEG_SUSPENDED;  /* Always indicate nothing was done */
+}
+
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Consume input data and store it in the full-image coefficient buffer.
+ * We read as much as one fully interleaved MCU row ("iMCU" row) per call,
+ * ie, v_samp_factor block rows for each component in the scan.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ */
+
+METHODDEF(int)
+consume_data (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+  JDIMENSION MCU_col_num;  /* index of current MCU within row */
+  int blkn, ci, xindex, yindex, yoffset;
+  JDIMENSION start_col;
+  JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+  JBLOCKROW buffer_ptr;
+  jpeg_component_info *compptr;
+
+  /* Align the virtual buffers for the components used in this scan. */
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    buffer[ci] = (*cinfo->mem->access_virt_barray)
+      ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+       cinfo->input_iMCU_row * compptr->v_samp_factor,
+       (JDIMENSION) compptr->v_samp_factor, TRUE);
+    /* Note: entropy decoder expects buffer to be zeroed,
+     * but this is handled automatically by the memory manager
+     * because we requested a pre-zeroed array.
+     */
+  }
+
+  /* Loop to process one whole iMCU row */
+  for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+       yoffset++) {
+    for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row;
+   MCU_col_num++) {
+      /* Construct list of pointers to DCT blocks belonging to this MCU */
+      blkn = 0;      /* index of current DCT block within MCU */
+      for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+  compptr = cinfo->cur_comp_info[ci];
+  start_col = MCU_col_num * compptr->MCU_width;
+  for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+    buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+    for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
+      coef->MCU_buffer[blkn++] = buffer_ptr++;
+    }
+  }
+      }
+      /* Try to fetch the MCU. */
+      if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) {
+  /* Suspension forced; update state counters and exit */
+  coef->MCU_vert_offset = yoffset;
+  coef->MCU_ctr = MCU_col_num;
+  return JPEG_SUSPENDED;
+      }
+    }
+    /* Completed an MCU row, but perhaps not an iMCU row */
+    coef->MCU_ctr = 0;
+  }
+  /* Completed the iMCU row, advance counters for next one */
+  if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
+    start_iMCU_row(cinfo);
+    return JPEG_ROW_COMPLETED;
+  }
+  /* Completed the scan */
+  (*cinfo->inputctl->finish_input_pass) (cinfo);
+  return JPEG_SCAN_COMPLETED;
+}
+
+
+/*
+ * Decompress and return some data in the multi-pass case.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image.
+ */
+
+METHODDEF(int)
+decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+  JDIMENSION block_num;
+  int ci, block_row, block_rows;
+  JBLOCKARRAY buffer;
+  JBLOCKROW buffer_ptr;
+  JSAMPARRAY output_ptr;
+  JDIMENSION output_col;
+  jpeg_component_info *compptr;
+  inverse_DCT_method_ptr inverse_DCT;
+
+  /* Force some input to be done if we are getting ahead of the input. */
+  while (cinfo->input_scan_number < cinfo->output_scan_number ||
+   (cinfo->input_scan_number == cinfo->output_scan_number &&
+    cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
+    if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+      return JPEG_SUSPENDED;
+  }
+
+  /* OK, output from the virtual arrays. */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Don't bother to IDCT an uninteresting component. */
+    if (! compptr->component_needed)
+      continue;
+    /* Align the virtual buffer for this component. */
+    buffer = (*cinfo->mem->access_virt_barray)
+      ((j_common_ptr) cinfo, coef->whole_image[ci],
+       cinfo->output_iMCU_row * compptr->v_samp_factor,
+       (JDIMENSION) compptr->v_samp_factor, FALSE);
+    /* Count non-dummy DCT block rows in this iMCU row. */
+    if (cinfo->output_iMCU_row < last_iMCU_row)
+      block_rows = compptr->v_samp_factor;
+    else {
+      /* NB: can't use last_row_height here; it is input-side-dependent! */
+      block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+      if (block_rows == 0) block_rows = compptr->v_samp_factor;
+    }
+    inverse_DCT = lossyd->inverse_DCT[ci];
+    output_ptr = output_buf[ci];
+    /* Loop over all DCT blocks to be processed. */
+    for (block_row = 0; block_row < block_rows; block_row++) {
+      buffer_ptr = buffer[block_row];
+      output_col = 0;
+      for (block_num = 0; block_num < compptr->width_in_data_units; block_num++) {
+  (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
+      output_ptr, output_col);
+  buffer_ptr++;
+  output_col += compptr->codec_data_unit;
+      }
+      output_ptr += compptr->codec_data_unit;
+    }
+  }
+
+  if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
+    return JPEG_ROW_COMPLETED;
+  return JPEG_SCAN_COMPLETED;
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+
+/*
+ * This code applies interblock smoothing as described by section K.8
+ * of the JPEG standard: the first 5 AC coefficients are estimated from
+ * the DC values of a DCT block and its 8 neighboring blocks.
+ * We apply smoothing only for progressive JPEG decoding, and only if
+ * the coefficients it can estimate are not yet known to full precision.
+ */
+
+/* Natural-order array positions of the first 5 zigzag-order coefficients */
+#define Q01_POS  1
+#define Q10_POS  8
+#define Q20_POS  16
+#define Q11_POS  9
+#define Q02_POS  2
+
+/*
+ * Determine whether block smoothing is applicable and safe.
+ * We also latch the current states of the coef_bits[] entries for the
+ * AC coefficients; otherwise, if the input side of the decompressor
+ * advances into a new scan, we might think the coefficients are known
+ * more accurately than they really are.
+ */
+
+LOCAL(boolean)
+smoothing_ok (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+  boolean smoothing_useful = FALSE;
+  int ci, coefi;
+  jpeg_component_info *compptr;
+  JQUANT_TBL * qtable;
+  int * coef_bits;
+  int * coef_bits_latch;
+
+  if (! cinfo->process == JPROC_PROGRESSIVE || cinfo->coef_bits == NULL)
+    return FALSE;
+
+  /* Allocate latch area if not already done */
+  if (coef->coef_bits_latch == NULL)
+    coef->coef_bits_latch = (int *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          cinfo->num_components *
+          (SAVED_COEFS * SIZEOF(int)));
+  coef_bits_latch = coef->coef_bits_latch;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* All components' quantization values must already be latched. */
+    if ((qtable = compptr->quant_table) == NULL)
+      return FALSE;
+    /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
+    if (qtable->quantval[0] == 0 ||
+  qtable->quantval[Q01_POS] == 0 ||
+  qtable->quantval[Q10_POS] == 0 ||
+  qtable->quantval[Q20_POS] == 0 ||
+  qtable->quantval[Q11_POS] == 0 ||
+  qtable->quantval[Q02_POS] == 0)
+      return FALSE;
+    /* DC values must be at least partly known for all components. */
+    coef_bits = cinfo->coef_bits[ci];
+    if (coef_bits[0] < 0)
+      return FALSE;
+    /* Block smoothing is helpful if some AC coefficients remain inaccurate. */
+    for (coefi = 1; coefi <= 5; coefi++) {
+      coef_bits_latch[coefi] = coef_bits[coefi];
+      if (coef_bits[coefi] != 0)
+  smoothing_useful = TRUE;
+    }
+    coef_bits_latch += SAVED_COEFS;
+  }
+
+  return smoothing_useful;
+}
+
+
+/*
+ * Variant of decompress_data for use when doing block smoothing.
+ */
+
+METHODDEF(int)
+decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+  JDIMENSION block_num, last_block_column;
+  int ci, block_row, block_rows, access_rows;
+  JBLOCKARRAY buffer;
+  JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
+  JSAMPARRAY output_ptr;
+  JDIMENSION output_col;
+  jpeg_component_info *compptr;
+  inverse_DCT_method_ptr inverse_DCT;
+  boolean first_row, last_row;
+  JBLOCK workspace;
+  int *coef_bits;
+  JQUANT_TBL *quanttbl;
+  INT32 Q00,Q01,Q02,Q10,Q11,Q20, num;
+  int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
+  int Al, pred;
+
+  /* Force some input to be done if we are getting ahead of the input. */
+  while (cinfo->input_scan_number <= cinfo->output_scan_number &&
+   ! cinfo->inputctl->eoi_reached) {
+    if (cinfo->input_scan_number == cinfo->output_scan_number) {
+      /* If input is working on current scan, we ordinarily want it to
+       * have completed the current row.  But if input scan is DC,
+       * we want it to keep one row ahead so that next block row's DC
+       * values are up to date.
+       */
+      JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
+      if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta)
+  break;
+    }
+    if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+      return JPEG_SUSPENDED;
+  }
+
+  /* OK, output from the virtual arrays. */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Don't bother to IDCT an uninteresting component. */
+    if (! compptr->component_needed)
+      continue;
+    /* Count non-dummy DCT block rows in this iMCU row. */
+    if (cinfo->output_iMCU_row < last_iMCU_row) {
+      block_rows = compptr->v_samp_factor;
+      access_rows = block_rows * 2; /* this and next iMCU row */
+      last_row = FALSE;
+    } else {
+      /* NB: can't use last_row_height here; it is input-side-dependent! */
+      block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+      if (block_rows == 0) block_rows = compptr->v_samp_factor;
+      access_rows = block_rows; /* this iMCU row only */
+      last_row = TRUE;
+    }
+    /* Align the virtual buffer for this component. */
+    if (cinfo->output_iMCU_row > 0) {
+      access_rows += compptr->v_samp_factor; /* prior iMCU row too */
+      buffer = (*cinfo->mem->access_virt_barray)
+  ((j_common_ptr) cinfo, coef->whole_image[ci],
+   (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
+   (JDIMENSION) access_rows, FALSE);
+      buffer += compptr->v_samp_factor;  /* point to current iMCU row */
+      first_row = FALSE;
+    } else {
+      buffer = (*cinfo->mem->access_virt_barray)
+  ((j_common_ptr) cinfo, coef->whole_image[ci],
+   (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE);
+      first_row = TRUE;
+    }
+    /* Fetch component-dependent info */
+    coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
+    quanttbl = compptr->quant_table;
+    Q00 = quanttbl->quantval[0];
+    Q01 = quanttbl->quantval[Q01_POS];
+    Q10 = quanttbl->quantval[Q10_POS];
+    Q20 = quanttbl->quantval[Q20_POS];
+    Q11 = quanttbl->quantval[Q11_POS];
+    Q02 = quanttbl->quantval[Q02_POS];
+    inverse_DCT = lossyd->inverse_DCT[ci];
+    output_ptr = output_buf[ci];
+    /* Loop over all DCT blocks to be processed. */
+    for (block_row = 0; block_row < block_rows; block_row++) {
+      buffer_ptr = buffer[block_row];
+      if (first_row && block_row == 0)
+  prev_block_row = buffer_ptr;
+      else
+  prev_block_row = buffer[block_row-1];
+      if (last_row && block_row == block_rows-1)
+  next_block_row = buffer_ptr;
+      else
+  next_block_row = buffer[block_row+1];
+      /* We fetch the surrounding DC values using a sliding-register approach.
+       * Initialize all nine here so as to do the right thing on narrow pics.
+       */
+      DC1 = DC2 = DC3 = (int) prev_block_row[0][0];
+      DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
+      DC7 = DC8 = DC9 = (int) next_block_row[0][0];
+      output_col = 0;
+      last_block_column = compptr->width_in_data_units - 1;
+      for (block_num = 0; block_num <= last_block_column; block_num++) {
+  /* Fetch current DCT block into workspace so we can modify it. */
+  jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
+  /* Update DC values */
+  if (block_num < last_block_column) {
+    DC3 = (int) prev_block_row[1][0];
+    DC6 = (int) buffer_ptr[1][0];
+    DC9 = (int) next_block_row[1][0];
+  }
+  /* Compute coefficient estimates per K.8.
+   * An estimate is applied only if coefficient is still zero,
+   * and is not known to be fully accurate.
+   */
+  /* AC01 */
+  if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) {
+    num = 36 * Q00 * (DC4 - DC6);
+    if (num >= 0) {
+      pred = (int) (((Q01<<7) + num) / (Q01<<8));
+      if (Al > 0 && pred >= (1<<Al))
+        pred = (1<<Al)-1;
+    } else {
+      pred = (int) (((Q01<<7) - num) / (Q01<<8));
+      if (Al > 0 && pred >= (1<<Al))
+        pred = (1<<Al)-1;
+      pred = -pred;
+    }
+    workspace[1] = (JCOEF) pred;
+  }
+  /* AC10 */
+  if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) {
+    num = 36 * Q00 * (DC2 - DC8);
+    if (num >= 0) {
+      pred = (int) (((Q10<<7) + num) / (Q10<<8));
+      if (Al > 0 && pred >= (1<<Al))
+        pred = (1<<Al)-1;
+    } else {
+      pred = (int) (((Q10<<7) - num) / (Q10<<8));
+      if (Al > 0 && pred >= (1<<Al))
+        pred = (1<<Al)-1;
+      pred = -pred;
+    }
+    workspace[8] = (JCOEF) pred;
+  }
+  /* AC20 */
+  if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) {
+    num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
+    if (num >= 0) {
+      pred = (int) (((Q20<<7) + num) / (Q20<<8));
+      if (Al > 0 && pred >= (1<<Al))
+        pred = (1<<Al)-1;
+    } else {
+      pred = (int) (((Q20<<7) - num) / (Q20<<8));
+      if (Al > 0 && pred >= (1<<Al))
+        pred = (1<<Al)-1;
+      pred = -pred;
+    }
+    workspace[16] = (JCOEF) pred;
+  }
+  /* AC11 */
+  if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) {
+    num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
+    if (num >= 0) {
+      pred = (int) (((Q11<<7) + num) / (Q11<<8));
+      if (Al > 0 && pred >= (1<<Al))
+        pred = (1<<Al)-1;
+    } else {
+      pred = (int) (((Q11<<7) - num) / (Q11<<8));
+      if (Al > 0 && pred >= (1<<Al))
+        pred = (1<<Al)-1;
+      pred = -pred;
+    }
+    workspace[9] = (JCOEF) pred;
+  }
+  /* AC02 */
+  if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) {
+    num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
+    if (num >= 0) {
+      pred = (int) (((Q02<<7) + num) / (Q02<<8));
+      if (Al > 0 && pred >= (1<<Al))
+        pred = (1<<Al)-1;
+    } else {
+      pred = (int) (((Q02<<7) - num) / (Q02<<8));
+      if (Al > 0 && pred >= (1<<Al))
+        pred = (1<<Al)-1;
+      pred = -pred;
+    }
+    workspace[2] = (JCOEF) pred;
+  }
+  /* OK, do the IDCT */
+  (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace,
+      output_ptr, output_col);
+  /* Advance for next column */
+  DC1 = DC2; DC2 = DC3;
+  DC4 = DC5; DC5 = DC6;
+  DC7 = DC8; DC8 = DC9;
+  buffer_ptr++, prev_block_row++, next_block_row++;
+  output_col += compptr->codec_data_unit;
+      }
+      output_ptr += compptr->codec_data_unit;
+    }
+  }
+
+  if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
+    return JPEG_ROW_COMPLETED;
+  return JPEG_SCAN_COMPLETED;
+}
+
+#endif /* BLOCK_SMOOTHING_SUPPORTED */
+
+
+/*
+ * Initialize coefficient buffer controller.
+ */
+
+GLOBAL(void)
+jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  d_coef_ptr coef;
+
+  coef = (d_coef_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(d_coef_controller));
+  lossyd->coef_private = (void *) coef;
+  lossyd->coef_start_input_pass = start_input_pass;
+  lossyd->coef_start_output_pass = start_output_pass;
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+  coef->coef_bits_latch = NULL;
+#endif
+
+  /* Create the coefficient buffer. */
+  if (need_full_buffer) {
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+    /* Allocate a full-image virtual array for each component, */
+    /* padded to a multiple of samp_factor DCT blocks in each direction. */
+    /* Note we ask for a pre-zeroed array. */
+    int ci, access_rows;
+    jpeg_component_info *compptr;
+
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      access_rows = compptr->v_samp_factor;
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+      /* If block smoothing could be used, need a bigger window */
+      if (cinfo->process == JPROC_PROGRESSIVE)
+  access_rows *= 3;
+#endif
+      coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
+  ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
+   (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+        (long) compptr->h_samp_factor),
+   (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+        (long) compptr->v_samp_factor),
+   (JDIMENSION) access_rows);
+    }
+    lossyd->pub.consume_data = consume_data;
+    lossyd->pub.decompress_data = decompress_data;
+    lossyd->coef_arrays = coef->whole_image; /* link to virtual arrays */
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+  } else {
+    /* We only need a single-MCU buffer. */
+    JBLOCKROW buffer;
+    int i;
+
+    buffer = (JBLOCKROW)
+      (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          D_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
+    for (i = 0; i < D_MAX_DATA_UNITS_IN_MCU; i++) {
+      coef->MCU_buffer[i] = buffer + i;
+    }
+    lossyd->pub.consume_data = dummy_consume_data;
+    lossyd->pub.decompress_data = decompress_onepass;
+    lossyd->coef_arrays = NULL; /* flag for no virtual arrays */
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdcolor.c b/Utilities/ITK/Utilities/itkjpeg/jdcolor.c
new file mode 100644
index 0000000000000000000000000000000000000000..7b0aa3d7bda56d78eddb5fb70f6c8021e4e85217
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdcolor.c
@@ -0,0 +1,414 @@
+/*
+ * jdcolor.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains output colorspace conversion routines.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private subobject */
+
+typedef struct {
+  struct jpeg_color_deconverter pub; /* public fields */
+
+  /* Private state for YCC->RGB conversion */
+  int * Cr_r_tab;    /* => table for Cr to R conversion */
+  int * Cb_b_tab;    /* => table for Cb to B conversion */
+  INT32 * Cr_g_tab;    /* => table for Cr to G conversion */
+  INT32 * Cb_g_tab;    /* => table for Cb to G conversion */
+} my_color_deconverter;
+
+typedef my_color_deconverter * my_cconvert_ptr;
+
+
+/**************** YCbCr -> RGB conversion: most common case **************/
+
+/*
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ *  R = Y                + 1.40200 * Cr
+ *  G = Y - 0.34414 * Cb - 0.71414 * Cr
+ *  B = Y + 1.77200 * Cb
+ * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
+ * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
+ *
+ * To avoid floating-point arithmetic, we represent the fractional constants
+ * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
+ * the products by 2^16, with appropriate rounding, to get the correct answer.
+ * Notice that Y, being an integral input, does not contribute any fraction
+ * so it need not participate in the rounding.
+ *
+ * For even more speed, we avoid doing any multiplications in the inner loop
+ * by precalculating the constants times Cb and Cr for all possible values.
+ * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
+ * for 12-bit samples it is still acceptable.  It's not very reasonable for
+ * 16-bit samples, but if you want lossless storage you shouldn't be changing
+ * colorspace anyway.
+ * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
+ * values for the G calculation are left scaled up, since we must add them
+ * together before rounding.
+ */
+
+#define SCALEBITS  16  /* speediest right-shift on some machines */
+#define ONE_HALF  ((INT32) 1 << (SCALEBITS-1))
+#define FIX(x)    ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+
+/*
+ * Initialize tables for YCC->RGB colorspace conversion.
+ */
+
+LOCAL(void)
+build_ycc_rgb_table (j_decompress_ptr cinfo)
+{
+  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+  int i;
+  INT32 x;
+#if BITS_IN_JSAMPLE == 16
+  /* no need for temporaries */
+#else
+  SHIFT_TEMPS
+#endif
+
+  cconvert->Cr_r_tab = (int *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        (MAXJSAMPLE+1) * SIZEOF(int));
+  cconvert->Cb_b_tab = (int *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        (MAXJSAMPLE+1) * SIZEOF(int));
+  cconvert->Cr_g_tab = (INT32 *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        (MAXJSAMPLE+1) * SIZEOF(INT32));
+  cconvert->Cb_g_tab = (INT32 *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        (MAXJSAMPLE+1) * SIZEOF(INT32));
+
+  for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
+    /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
+    /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
+
+#if BITS_IN_JSAMPLE == 16
+    /* Bug fix 2001-11-06 by Eichelberg: The integer routines below
+       produce an overflow when used with MAXJSAMPLE == 65535.
+       Use floating point calculation instead. */
+
+    /* Cr=>R value is nearest int to 1.40200 * x */
+    cconvert->Cr_r_tab[i] = (int)(1.40200 * (double)x + 0.5);
+    /* Cb=>B value is nearest int to 1.77200 * x */
+    cconvert->Cb_b_tab[i] = (int)(1.77200 * (double)x + 0.5);
+#else
+    /* Cr=>R value is nearest int to 1.40200 * x */
+    cconvert->Cr_r_tab[i] = (int)
+        RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
+    /* Cb=>B value is nearest int to 1.77200 * x */
+    cconvert->Cb_b_tab[i] = (int)
+        RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
+#endif
+
+    /* Cr=>G value is scaled-up -0.71414 * x */
+    cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
+    /* Cb=>G value is scaled-up -0.34414 * x */
+    /* We also add in ONE_HALF so that need not do it in inner loop */
+    cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
+  }
+}
+
+
+/*
+ * Convert some rows of samples to the output colorspace.
+ *
+ * Note that we change from noninterleaved, one-plane-per-component format
+ * to interleaved-pixel format.  The output buffer is therefore three times
+ * as wide as the input buffer.
+ * A starting row offset is provided only for the input buffer.  The caller
+ * can easily adjust the passed output_buf value to accommodate any row
+ * offset required on that side.
+ */
+
+METHODDEF(void)
+ycc_rgb_convert (j_decompress_ptr cinfo,
+     JSAMPIMAGE input_buf, JDIMENSION input_row,
+     JSAMPARRAY output_buf, int num_rows)
+{
+  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+  register int y, cb, cr;
+  register JSAMPROW outptr;
+  register JSAMPROW inptr0, inptr1, inptr2;
+  register JDIMENSION col;
+  JDIMENSION num_cols = cinfo->output_width;
+  /* copy these pointers into registers if possible */
+  register JSAMPLE * range_limit = cinfo->sample_range_limit;
+  register int * Crrtab = cconvert->Cr_r_tab;
+  register int * Cbbtab = cconvert->Cb_b_tab;
+  register INT32 * Crgtab = cconvert->Cr_g_tab;
+  register INT32 * Cbgtab = cconvert->Cb_g_tab;
+  SHIFT_TEMPS
+
+  while (--num_rows >= 0) {
+    inptr0 = input_buf[0][input_row];
+    inptr1 = input_buf[1][input_row];
+    inptr2 = input_buf[2][input_row];
+    input_row++;
+    outptr = *output_buf++;
+    for (col = 0; col < num_cols; col++) {
+      y  = GETJSAMPLE(inptr0[col]);
+      cb = GETJSAMPLE(inptr1[col]);
+      cr = GETJSAMPLE(inptr2[col]);
+      /* Range-limiting is essential due to noise introduced by DCT losses. */
+      outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
+      outptr[RGB_GREEN] = range_limit[y +
+            ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+             SCALEBITS))];
+      outptr[RGB_BLUE] =  range_limit[y + Cbbtab[cb]];
+      outptr += RGB_PIXELSIZE;
+    }
+  }
+}
+
+
+/**************** Cases other than YCbCr -> RGB **************/
+
+
+/*
+ * Color conversion for no colorspace change: just copy the data,
+ * converting from separate-planes to interleaved representation.
+ */
+
+METHODDEF(void)
+null_convert (j_decompress_ptr cinfo,
+        JSAMPIMAGE input_buf, JDIMENSION input_row,
+        JSAMPARRAY output_buf, int num_rows)
+{
+  register JSAMPROW inptr, outptr;
+  register JDIMENSION count;
+  register int num_components = cinfo->num_components;
+  JDIMENSION num_cols = cinfo->output_width;
+  int ci;
+
+  while (--num_rows >= 0) {
+    for (ci = 0; ci < num_components; ci++) {
+      inptr = input_buf[ci][input_row];
+      outptr = output_buf[0] + ci;
+      for (count = num_cols; count > 0; count--) {
+  *outptr = *inptr++;  /* needn't bother with GETJSAMPLE() here */
+  outptr += num_components;
+      }
+    }
+    input_row++;
+    output_buf++;
+  }
+}
+
+
+/*
+ * Color conversion for grayscale: just copy the data.
+ * This also works for YCbCr -> grayscale conversion, in which
+ * we just copy the Y (luminance) component and ignore chrominance.
+ */
+
+METHODDEF(void)
+grayscale_convert (j_decompress_ptr cinfo,
+       JSAMPIMAGE input_buf, JDIMENSION input_row,
+       JSAMPARRAY output_buf, int num_rows)
+{
+  jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
+        num_rows, cinfo->output_width);
+}
+
+
+/*
+ * Convert grayscale to RGB: just duplicate the graylevel three times.
+ * This is provided to support applications that don't want to cope
+ * with grayscale as a separate case.
+ */
+
+METHODDEF(void)
+gray_rgb_convert (j_decompress_ptr cinfo,
+      JSAMPIMAGE input_buf, JDIMENSION input_row,
+      JSAMPARRAY output_buf, int num_rows)
+{
+  register JSAMPROW inptr, outptr;
+  register JDIMENSION col;
+  JDIMENSION num_cols = cinfo->output_width;
+
+  while (--num_rows >= 0) {
+    inptr = input_buf[0][input_row++];
+    outptr = *output_buf++;
+    for (col = 0; col < num_cols; col++) {
+      /* We can dispense with GETJSAMPLE() here */
+      outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
+      outptr += RGB_PIXELSIZE;
+    }
+  }
+}
+
+
+/*
+ * Adobe-style YCCK->CMYK conversion.
+ * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
+ * conversion as above, while passing K (black) unchanged.
+ * We assume build_ycc_rgb_table has been called.
+ */
+
+METHODDEF(void)
+ycck_cmyk_convert (j_decompress_ptr cinfo,
+       JSAMPIMAGE input_buf, JDIMENSION input_row,
+       JSAMPARRAY output_buf, int num_rows)
+{
+  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+  register int y, cb, cr;
+  register JSAMPROW outptr;
+  register JSAMPROW inptr0, inptr1, inptr2, inptr3;
+  register JDIMENSION col;
+  JDIMENSION num_cols = cinfo->output_width;
+  /* copy these pointers into registers if possible */
+  register JSAMPLE * range_limit = cinfo->sample_range_limit;
+  register int * Crrtab = cconvert->Cr_r_tab;
+  register int * Cbbtab = cconvert->Cb_b_tab;
+  register INT32 * Crgtab = cconvert->Cr_g_tab;
+  register INT32 * Cbgtab = cconvert->Cb_g_tab;
+  SHIFT_TEMPS
+
+  while (--num_rows >= 0) {
+    inptr0 = input_buf[0][input_row];
+    inptr1 = input_buf[1][input_row];
+    inptr2 = input_buf[2][input_row];
+    inptr3 = input_buf[3][input_row];
+    input_row++;
+    outptr = *output_buf++;
+    for (col = 0; col < num_cols; col++) {
+      y  = GETJSAMPLE(inptr0[col]);
+      cb = GETJSAMPLE(inptr1[col]);
+      cr = GETJSAMPLE(inptr2[col]);
+      /* Range-limiting is essential due to noise introduced by DCT losses. */
+      outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])];  /* red */
+      outptr[1] = range_limit[MAXJSAMPLE - (y +      /* green */
+            ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+             SCALEBITS)))];
+      outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])];  /* blue */
+      /* K passes through unchanged */
+      outptr[3] = inptr3[col];  /* don't need GETJSAMPLE here */
+      outptr += 4;
+    }
+  }
+}
+
+
+/*
+ * Empty method for start_pass.
+ */
+
+METHODDEF(void)
+start_pass_dcolor (j_decompress_ptr cinfo)
+{
+  (void)cinfo;
+  /* no work needed */
+}
+
+
+/*
+ * Module initialization routine for output colorspace conversion.
+ */
+
+GLOBAL(void)
+jinit_color_deconverter (j_decompress_ptr cinfo)
+{
+  my_cconvert_ptr cconvert;
+  int ci;
+
+  cconvert = (my_cconvert_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_color_deconverter));
+  cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
+  cconvert->pub.start_pass = start_pass_dcolor;
+
+  /* Make sure num_components agrees with jpeg_color_space */
+  switch (cinfo->jpeg_color_space) {
+  case JCS_GRAYSCALE:
+    if (cinfo->num_components != 1)
+      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+    break;
+
+  case JCS_RGB:
+  case JCS_YCbCr:
+    if (cinfo->num_components != 3)
+      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+    break;
+
+  case JCS_CMYK:
+  case JCS_YCCK:
+    if (cinfo->num_components != 4)
+      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+    break;
+
+  default:      /* JCS_UNKNOWN can be anything */
+    if (cinfo->num_components < 1)
+      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+    break;
+  }
+
+  /* Set out_color_components and conversion method based on requested space.
+   * Also clear the component_needed flags for any unused components,
+   * so that earlier pipeline stages can avoid useless computation.
+   */
+
+  switch (cinfo->out_color_space) {
+  case JCS_GRAYSCALE:
+    cinfo->out_color_components = 1;
+    if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
+  cinfo->jpeg_color_space == JCS_YCbCr) {
+      cconvert->pub.color_convert = grayscale_convert;
+      /* For color->grayscale conversion, only the Y (0) component is needed */
+      for (ci = 1; ci < cinfo->num_components; ci++)
+  cinfo->comp_info[ci].component_needed = FALSE;
+    } else
+      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+    break;
+
+  case JCS_RGB:
+    cinfo->out_color_components = RGB_PIXELSIZE;
+    if (cinfo->jpeg_color_space == JCS_YCbCr) {
+      cconvert->pub.color_convert = ycc_rgb_convert;
+      build_ycc_rgb_table(cinfo);
+    } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
+      cconvert->pub.color_convert = gray_rgb_convert;
+    } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
+      cconvert->pub.color_convert = null_convert;
+    } else
+      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+    break;
+
+  case JCS_CMYK:
+    cinfo->out_color_components = 4;
+    if (cinfo->jpeg_color_space == JCS_YCCK) {
+      cconvert->pub.color_convert = ycck_cmyk_convert;
+      build_ycc_rgb_table(cinfo);
+    } else if (cinfo->jpeg_color_space == JCS_CMYK) {
+      cconvert->pub.color_convert = null_convert;
+    } else
+      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+    break;
+
+  default:
+    /* Permit null conversion to same output space */
+    if (cinfo->out_color_space == cinfo->jpeg_color_space) {
+      cinfo->out_color_components = cinfo->num_components;
+      cconvert->pub.color_convert = null_convert;
+    } else      /* unsupported non-null conversion */
+      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+    break;
+  }
+
+  if (cinfo->quantize_colors)
+    cinfo->output_components = 1; /* single colormapped output component */
+  else
+    cinfo->output_components = cinfo->out_color_components;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdct.h b/Utilities/ITK/Utilities/itkjpeg/jdct.h
new file mode 100644
index 0000000000000000000000000000000000000000..ffdd5e50bed24bdb5bd19eabc229e829e8f0e1de
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdct.h
@@ -0,0 +1,176 @@
+/*
+ * jdct.h
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file contains common declarations for the forward and
+ * inverse DCT modules.  These declarations are private to the DCT managers
+ * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
+ * The individual DCT algorithms are kept in separate files to ease 
+ * machine-dependent tuning (e.g., assembly coding).
+ */
+
+
+/*
+ * A forward DCT routine is given a pointer to a work area of type DCTELEM[];
+ * the DCT is to be performed in-place in that buffer.  Type DCTELEM is int
+ * for 8-bit samples, INT32 for 12-bit samples.  (NOTE: Floating-point DCT
+ * implementations use an array of type FAST_FLOAT, instead.)
+ * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
+ * The DCT outputs are returned scaled up by a factor of 8; they therefore
+ * have a range of +-8K for 8-bit data, +-128K for 12-bit data.  This
+ * convention improves accuracy in integer implementations and saves some
+ * work in floating-point ones.
+ * Quantization of the output coefficients is done by jcdctmgr.c.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef int DCTELEM;    /* 16 or 32 bits is fine */
+#else
+typedef INT32 DCTELEM;    /* must have 32 bits */
+#endif
+
+typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data));
+typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data));
+
+
+/*
+ * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
+ * to an output sample array.  The routine must dequantize the input data as
+ * well as perform the IDCT; for dequantization, it uses the multiplier table
+ * pointed to by compptr->dct_table.  The output data is to be placed into the
+ * sample array starting at a specified column.  (Any row offset needed will
+ * be applied to the array pointer before it is passed to the IDCT code.)
+ * Note that the number of samples emitted by the IDCT routine is
+ * DCT_scaled_size * DCT_scaled_size.
+ */
+
+/* typedef inverse_DCT_method_ptr is declared in jpegint.h */
+
+/*
+ * Each IDCT routine has its own ideas about the best dct_table element type.
+ */
+
+typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
+#if BITS_IN_JSAMPLE == 8
+typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
+#define IFAST_SCALE_BITS  2  /* fractional bits in scale factors */
+#else
+typedef INT32 IFAST_MULT_TYPE;  /* need 32 bits for scaled quantizers */
+#define IFAST_SCALE_BITS  13  /* fractional bits in scale factors */
+#endif
+typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
+
+
+/*
+ * Each IDCT routine is responsible for range-limiting its results and
+ * converting them to unsigned form (0..MAXJSAMPLE).  The raw outputs could
+ * be quite far out of range if the input data is corrupt, so a bulletproof
+ * range-limiting step is required.  We use a mask-and-table-lookup method
+ * to do the combined operations quickly.  See the comments with
+ * prepare_range_limit_table (in jdmaster.c) for more info.
+ */
+
+#define IDCT_range_limit(cinfo)  ((cinfo)->sample_range_limit + CENTERJSAMPLE)
+
+#define RANGE_MASK  (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_fdct_islow    jFDislow
+#define jpeg_fdct_ifast    jFDifast
+#define jpeg_fdct_float    jFDfloat
+#define jpeg_idct_islow    jRDislow
+#define jpeg_idct_ifast    jRDifast
+#define jpeg_idct_float    jRDfloat
+#define jpeg_idct_4x4    jRD4x4
+#define jpeg_idct_2x2    jRD2x2
+#define jpeg_idct_1x1    jRD1x1
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+/* Extern declarations for the forward and inverse DCT routines. */
+
+EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data));
+EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data));
+EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data));
+
+EXTERN(void) jpeg_idct_islow
+    JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+   JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_ifast
+    JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+   JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_float
+    JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+   JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_4x4
+    JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+   JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_2x2
+    JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+   JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_1x1
+    JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+   JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+
+
+/*
+ * Macros for handling fixed-point arithmetic; these are used by many
+ * but not all of the DCT/IDCT modules.
+ *
+ * All values are expected to be of type INT32.
+ * Fractional constants are scaled left by CONST_BITS bits.
+ * CONST_BITS is defined within each module using these macros,
+ * and may differ from one module to the next.
+ */
+
+#define ONE  ((INT32) 1)
+#define CONST_SCALE (ONE << CONST_BITS)
+
+/* Convert a positive real constant to an integer scaled by CONST_SCALE.
+ * Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
+ * thus causing a lot of useless floating-point operations at run time.
+ */
+
+#define FIX(x)  ((INT32) ((x) * CONST_SCALE + 0.5))
+
+/* Descale and correctly round an INT32 value that's scaled by N bits.
+ * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
+ * the fudge factor is correct for either sign of X.
+ */
+
+#define DESCALE(x,n)  RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * This macro is used only when the two inputs will actually be no more than
+ * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
+ * full 32x32 multiply.  This provides a useful speedup on many machines.
+ * Unfortunately there is no way to specify a 16x16->32 multiply portably
+ * in C, but some C compilers will do the right thing if you provide the
+ * correct combination of casts.
+ */
+
+#ifdef SHORTxSHORT_32    /* may work if 'int' is 32 bits */
+#define MULTIPLY16C16(var,const)  (((INT16) (var)) * ((INT16) (const)))
+#endif
+#ifdef SHORTxLCONST_32    /* known to work with Microsoft C 6.0 */
+#define MULTIPLY16C16(var,const)  (((INT16) (var)) * ((INT32) (const)))
+#endif
+
+#ifndef MULTIPLY16C16    /* default definition */
+#define MULTIPLY16C16(var,const)  ((var) * (const))
+#endif
+
+/* Same except both inputs are variables. */
+
+#ifdef SHORTxSHORT_32    /* may work if 'int' is 32 bits */
+#define MULTIPLY16V16(var1,var2)  (((INT16) (var1)) * ((INT16) (var2)))
+#endif
+
+#ifndef MULTIPLY16V16    /* default definition */
+#define MULTIPLY16V16(var1,var2)  ((var1) * (var2))
+#endif
diff --git a/Utilities/ITK/Utilities/itkjpeg/jddctmgr.c b/Utilities/ITK/Utilities/itkjpeg/jddctmgr.c
new file mode 100644
index 0000000000000000000000000000000000000000..6f6c4442bd9f19fd6f9516a99dd929c573c424d8
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jddctmgr.c
@@ -0,0 +1,270 @@
+/*
+ * jddctmgr.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the inverse-DCT management logic.
+ * This code selects a particular IDCT implementation to be used,
+ * and it performs related housekeeping chores.  No code in this file
+ * is executed per IDCT step, only during output pass setup.
+ *
+ * Note that the IDCT routines are responsible for performing coefficient
+ * dequantization as well as the IDCT proper.  This module sets up the
+ * dequantization multiplier table needed by the IDCT routine.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"    /* Private declarations for lossy subsystem */
+#include "jdct.h"    /* Private declarations for DCT subsystem */
+
+
+/*
+ * The decompressor input side (jdinput.c) saves away the appropriate
+ * quantization table for each component at the start of the first scan
+ * involving that component.  (This is necessary in order to correctly
+ * decode files that reuse Q-table slots.)
+ * When we are ready to make an output pass, the saved Q-table is converted
+ * to a multiplier table that will actually be used by the IDCT routine.
+ * The multiplier table contents are IDCT-method-dependent.  To support
+ * application changes in IDCT method between scans, we can remake the
+ * multiplier tables if necessary.
+ * In buffered-image mode, the first output pass may occur before any data
+ * has been seen for some components, and thus before their Q-tables have
+ * been saved away.  To handle this case, multiplier tables are preset
+ * to zeroes; the result of the IDCT will be a neutral gray level.
+ */
+
+
+/* Private subobject for this module */
+
+typedef struct {
+  /* This array contains the IDCT method code that each multiplier table
+   * is currently set up for, or -1 if it's not yet set up.
+   * The actual multiplier tables are pointed to by dct_table in the
+   * per-component comp_info structures.
+   */
+  int cur_method[MAX_COMPONENTS];
+} idct_controller;
+
+typedef idct_controller * idct_ptr;
+
+
+/* Allocated multiplier tables: big enough for any supported variant */
+
+typedef union {
+  ISLOW_MULT_TYPE islow_array[DCTSIZE2];
+#ifdef DCT_IFAST_SUPPORTED
+  IFAST_MULT_TYPE ifast_array[DCTSIZE2];
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+  FLOAT_MULT_TYPE float_array[DCTSIZE2];
+#endif
+} multiplier_table;
+
+
+/* The current scaled-IDCT routines require ISLOW-style multiplier tables,
+ * so be sure to compile that code if either ISLOW or SCALING is requested.
+ */
+#ifdef DCT_ISLOW_SUPPORTED
+#define PROVIDE_ISLOW_TABLES
+#else
+#ifdef IDCT_SCALING_SUPPORTED
+#define PROVIDE_ISLOW_TABLES
+#endif
+#endif
+
+
+/*
+ * Prepare for an output pass.
+ * Here we select the proper IDCT routine for each component and build
+ * a matching multiplier table.
+ */
+
+METHODDEF(void)
+start_pass (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  idct_ptr idct = (idct_ptr) lossyd->idct_private;
+  int ci, i;
+  jpeg_component_info *compptr;
+  int method = 0;
+  inverse_DCT_method_ptr method_ptr = NULL;
+  JQUANT_TBL * qtbl;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Select the proper IDCT routine for this component's scaling */
+    switch (compptr->codec_data_unit) {
+#ifdef IDCT_SCALING_SUPPORTED
+    case 1:
+      method_ptr = jpeg_idct_1x1;
+      method = JDCT_ISLOW;  /* jidctred uses islow-style table */
+      break;
+    case 2:
+      method_ptr = jpeg_idct_2x2;
+      method = JDCT_ISLOW;  /* jidctred uses islow-style table */
+      break;
+    case 4:
+      method_ptr = jpeg_idct_4x4;
+      method = JDCT_ISLOW;  /* jidctred uses islow-style table */
+      break;
+#endif
+    case DCTSIZE:
+      switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+      case JDCT_ISLOW:
+  method_ptr = jpeg_idct_islow;
+  method = JDCT_ISLOW;
+  break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+      case JDCT_IFAST:
+  method_ptr = jpeg_idct_ifast;
+  method = JDCT_IFAST;
+  break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+      case JDCT_FLOAT:
+  method_ptr = jpeg_idct_float;
+  method = JDCT_FLOAT;
+  break;
+#endif
+      default:
+  ERREXIT(cinfo, JERR_NOT_COMPILED);
+  break;
+      }
+      break;
+    default:
+      ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->codec_data_unit);
+      break;
+    }
+    lossyd->inverse_DCT[ci] = method_ptr;
+    /* Create multiplier table from quant table.
+     * However, we can skip this if the component is uninteresting
+     * or if we already built the table.  Also, if no quant table
+     * has yet been saved for the component, we leave the
+     * multiplier table all-zero; we'll be reading zeroes from the
+     * coefficient controller's buffer anyway.
+     */
+    if (! compptr->component_needed || idct->cur_method[ci] == method)
+      continue;
+    qtbl = compptr->quant_table;
+    if (qtbl == NULL)    /* happens if no data yet for component */
+      continue;
+    idct->cur_method[ci] = method;
+    switch (method) {
+#ifdef PROVIDE_ISLOW_TABLES
+    case JDCT_ISLOW:
+      {
+  /* For LL&M IDCT method, multipliers are equal to raw quantization
+   * coefficients, but are stored as ints to ensure access efficiency.
+   */
+  ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
+  for (i = 0; i < DCTSIZE2; i++) {
+    ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
+  }
+      }
+      break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+    case JDCT_IFAST:
+      {
+  /* For AA&N IDCT method, multipliers are equal to quantization
+   * coefficients scaled by scalefactor[row]*scalefactor[col], where
+   *   scalefactor[0] = 1
+   *   scalefactor[k] = cos(k*PI/16) * sqrt(2)    for k=1..7
+   * For integer operation, the multiplier table is to be scaled by
+   * IFAST_SCALE_BITS.
+   */
+  IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
+#define CONST_BITS 14
+  static const INT16 aanscales[DCTSIZE2] = {
+    /* precomputed values scaled up by 14 bits */
+    16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
+    22725, 31521, 29692, 26722, 22725, 17855, 12299,  6270,
+    21407, 29692, 27969, 25172, 21407, 16819, 11585,  5906,
+    19266, 26722, 25172, 22654, 19266, 15137, 10426,  5315,
+    16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
+    12873, 17855, 16819, 15137, 12873, 10114,  6967,  3552,
+     8867, 12299, 11585, 10426,  8867,  6967,  4799,  2446,
+     4520,  6270,  5906,  5315,  4520,  3552,  2446,  1247
+  };
+  SHIFT_TEMPS
+
+  for (i = 0; i < DCTSIZE2; i++) {
+    ifmtbl[i] = (IFAST_MULT_TYPE)
+      DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
+          (INT32) aanscales[i]),
+        CONST_BITS-IFAST_SCALE_BITS);
+  }
+      }
+      break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+    case JDCT_FLOAT:
+      {
+  /* For float AA&N IDCT method, multipliers are equal to quantization
+   * coefficients scaled by scalefactor[row]*scalefactor[col], where
+   *   scalefactor[0] = 1
+   *   scalefactor[k] = cos(k*PI/16) * sqrt(2)    for k=1..7
+   */
+  FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
+  int row, col;
+  static const double aanscalefactor[DCTSIZE] = {
+    1.0, 1.387039845, 1.306562965, 1.175875602,
+    1.0, 0.785694958, 0.541196100, 0.275899379
+  };
+
+  i = 0;
+  for (row = 0; row < DCTSIZE; row++) {
+    for (col = 0; col < DCTSIZE; col++) {
+      fmtbl[i] = (FLOAT_MULT_TYPE)
+        ((double) qtbl->quantval[i] *
+         aanscalefactor[row] * aanscalefactor[col]);
+      i++;
+    }
+  }
+      }
+      break;
+#endif
+    default:
+      ERREXIT(cinfo, JERR_NOT_COMPILED);
+      break;
+    }
+  }
+}
+
+
+/*
+ * Initialize IDCT manager.
+ */
+
+GLOBAL(void)
+jinit_inverse_dct (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  idct_ptr idct;
+  int ci;
+  jpeg_component_info *compptr;
+
+  idct = (idct_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(idct_controller));
+  lossyd->idct_private = (void *) idct;
+  lossyd->idct_start_pass = start_pass;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Allocate and pre-zero a multiplier table for each component */
+    compptr->dct_table =
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          SIZEOF(multiplier_table));
+    MEMZERO(compptr->dct_table, SIZEOF(multiplier_table));
+    /* Mark multiplier table not yet set up for any method */
+    idct->cur_method[ci] = -1;
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jddiffct.c b/Utilities/ITK/Utilities/itkjpeg/jddiffct.c
new file mode 100644
index 0000000000000000000000000000000000000000..6dc61e44569788272aeed1e7f109171656c1c375
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jddiffct.c
@@ -0,0 +1,400 @@
+/*
+ * jddiffct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the [un]difference buffer controller for decompression.
+ * This controller is the top level of the lossless JPEG decompressor proper.
+ * The difference buffer lies between the entropy decoding and
+ * prediction/undifferencing steps.  The undifference buffer lies between the
+ * prediction/undifferencing and scaling steps.
+ *
+ * In buffered-image mode, this controller is the interface between
+ * input-oriented processing and output-oriented processing.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossls.h"
+
+
+#ifdef D_LOSSLESS_SUPPORTED
+
+/* Private buffer controller object */
+
+typedef struct {
+  /* These variables keep track of the current location of the input side. */
+  /* cinfo->input_iMCU_row is also used for this. */
+  JDIMENSION MCU_ctr;    /* counts MCUs processed in current row */
+  unsigned int restart_rows_to_go;  /* MCU-rows left in this restart interval */
+  unsigned int MCU_vert_offset;    /* counts MCU rows within iMCU row */
+  unsigned int MCU_rows_per_iMCU_row;  /* number of such rows needed */
+
+  /* The output side's location is represented by cinfo->output_iMCU_row. */
+
+  JDIFFARRAY diff_buf[MAX_COMPONENTS];  /* iMCU row of differences */
+  JDIFFARRAY undiff_buf[MAX_COMPONENTS]; /* iMCU row of undiff'd samples */
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+  /* In multi-pass modes, we need a virtual sample array for each component. */
+  jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
+#endif
+} d_diff_controller;
+
+typedef d_diff_controller * d_diff_ptr;
+
+/* Forward declarations */
+METHODDEF(int) decompress_data
+  JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+METHODDEF(int) output_data
+  JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_decompress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row (input side) */
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+
+  /* In an interleaved scan, an MCU row is the same as an iMCU row.
+   * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+   * But at the bottom of the image, process only what's left.
+   */
+  if (cinfo->comps_in_scan > 1) {
+    diff->MCU_rows_per_iMCU_row = 1;
+  } else {
+    if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
+      diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+    else
+      diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+  }
+
+  diff->MCU_ctr = 0;
+  diff->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+
+  /* Check that the restart interval is an integer multiple of the number 
+   * of MCU in an MCU-row.
+   */
+  if (cinfo->restart_interval % cinfo->MCUs_per_row != 0)
+    ERREXIT2(cinfo, JERR_BAD_RESTART,
+       cinfo->restart_interval, cinfo->MCUs_per_row);
+
+  /* Initialize restart counter */
+  diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row;
+
+  cinfo->input_iMCU_row = 0;
+  start_iMCU_row(cinfo);
+}
+
+
+/*
+ * Check for a restart marker & resynchronize decoder, undifferencer.
+ * Returns FALSE if must suspend.
+ */
+
+METHODDEF(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+
+  if (! (*losslsd->entropy_process_restart) (cinfo))
+    return FALSE;
+
+  (*losslsd->predict_process_restart) (cinfo);
+
+  /* Reset restart counter */
+  diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row;
+
+  return TRUE;
+}
+
+
+/*
+ * Initialize for an output processing pass.
+ */
+
+METHODDEF(void)
+start_output_pass (j_decompress_ptr cinfo)
+{
+  cinfo->output_iMCU_row = 0;
+}
+
+
+/*
+ * Decompress and return some data in the supplied buffer.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Input and output must run in lockstep since we have only a one-MCU buffer.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(int)
+decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+  JDIMENSION MCU_col_num;  /* index of current MCU within row */
+  JDIMENSION MCU_count;    /* number of MCUs decoded */
+  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+  int comp, ci, row, prev_row;
+  unsigned int yoffset;
+  jpeg_component_info *compptr;
+
+  /* Loop to process as much as one whole iMCU row */
+  for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row;
+       yoffset++) {
+
+    /* Process restart marker if needed; may have to suspend */
+    if (cinfo->restart_interval) {
+      if (diff->restart_rows_to_go == 0)
+  if (! process_restart(cinfo))
+    return JPEG_SUSPENDED;
+    }
+
+    MCU_col_num = diff->MCU_ctr;
+    /* Try to fetch an MCU-row (or remaining portion of suspended MCU-row). */
+    MCU_count =
+      (*losslsd->entropy_decode_mcus) (cinfo,
+               diff->diff_buf, yoffset, MCU_col_num,
+               cinfo->MCUs_per_row - MCU_col_num);
+    if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) {
+      /* Suspension forced; update state counters and exit */
+      diff->MCU_vert_offset = yoffset;
+      diff->MCU_ctr += MCU_count;
+      return JPEG_SUSPENDED;
+    }
+
+    /* Account for restart interval (no-op if not using restarts) */
+    diff->restart_rows_to_go--;
+
+    /* Completed an MCU row, but perhaps not an iMCU row */
+    diff->MCU_ctr = 0;
+  }
+
+  /*
+   * Undifference and scale each scanline of the disassembled MCU-row
+   * separately.  We do not process dummy samples at the end of a scanline
+   * or dummy rows at the end of the image.
+   */
+  for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
+    compptr = cinfo->cur_comp_info[comp];
+    ci = compptr->component_index;
+    for (row = 0, prev_row = compptr->v_samp_factor - 1;
+   row < (cinfo->input_iMCU_row == last_iMCU_row ?
+    compptr->last_row_height : compptr->v_samp_factor);
+   prev_row = row, row++) {
+      (*losslsd->predict_undifference[ci]) (cinfo, ci,
+              diff->diff_buf[ci][row],
+              diff->undiff_buf[ci][prev_row],
+              diff->undiff_buf[ci][row],
+              compptr->width_in_data_units);
+      (*losslsd->scaler_scale) (cinfo, diff->undiff_buf[ci][row],
+        output_buf[ci][row],
+        compptr->width_in_data_units);
+    }
+  }
+
+  /* Completed the iMCU row, advance counters for next one.
+   *
+   * NB: output_data will increment output_iMCU_row.
+   * This counter is not needed for the single-pass case
+   * or the input side of the multi-pass case.
+   */
+  if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
+    start_iMCU_row(cinfo);
+    return JPEG_ROW_COMPLETED;
+  }
+  /* Completed the scan */
+  (*cinfo->inputctl->finish_input_pass) (cinfo);
+  return JPEG_SCAN_COMPLETED;
+}
+
+
+/*
+ * Dummy consume-input routine for single-pass operation.
+ */
+
+METHODDEF(int)
+dummy_consume_data (j_decompress_ptr cinfo)
+{
+  (void)cinfo;
+  return JPEG_SUSPENDED;  /* Always indicate nothing was done */
+}
+
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Consume input data and store it in the full-image sample buffer.
+ * We read as much as one fully interleaved MCU row ("iMCU" row) per call,
+ * ie, v_samp_factor rows for each component in the scan.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ */
+
+METHODDEF(int)
+consume_data (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+  /* JDIMENSION MCU_col_num; */  /* index of current MCU within row */
+  /* JDIMENSION MCU_count; */  /* number of MCUs decoded */
+  /* JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; */
+  int comp, ci /* , yoffset, row, prev_row */;
+  JSAMPARRAY buffer[MAX_COMPS_IN_SCAN];
+  jpeg_component_info *compptr;
+
+  /* Align the virtual buffers for the components used in this scan. */
+  for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
+    compptr = cinfo->cur_comp_info[comp];
+    ci = compptr->component_index;
+    buffer[ci] = (*cinfo->mem->access_virt_sarray)
+      ((j_common_ptr) cinfo, diff->whole_image[ci],
+       cinfo->input_iMCU_row * compptr->v_samp_factor,
+       (JDIMENSION) compptr->v_samp_factor, TRUE);
+  }
+
+  return decompress_data(cinfo, buffer);
+}
+
+
+/*
+ * Output some data from the full-image buffer sample in the multi-pass case.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image.
+ */
+
+METHODDEF(int)
+output_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+  JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+  int ci, samp_rows, row;
+  JSAMPARRAY buffer;
+  jpeg_component_info *compptr;
+
+  /* Force some input to be done if we are getting ahead of the input. */
+  while (cinfo->input_scan_number < cinfo->output_scan_number ||
+   (cinfo->input_scan_number == cinfo->output_scan_number &&
+    cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
+    if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+      return JPEG_SUSPENDED;
+  }
+
+  /* OK, output from the virtual arrays. */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Align the virtual buffer for this component. */
+    buffer = (*cinfo->mem->access_virt_sarray)
+      ((j_common_ptr) cinfo, diff->whole_image[ci],
+       cinfo->output_iMCU_row * compptr->v_samp_factor,
+       (JDIMENSION) compptr->v_samp_factor, FALSE);
+
+    if (cinfo->output_iMCU_row < last_iMCU_row)
+      samp_rows = compptr->v_samp_factor;
+    else {
+      /* NB: can't use last_row_height here; it is input-side-dependent! */
+      samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+      if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
+    }
+
+    for (row = 0; row < samp_rows; row++) {
+      MEMCOPY(output_buf[ci][row], buffer[row],
+        compptr->width_in_data_units * SIZEOF(JSAMPLE));
+    }
+  }
+
+  if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
+    return JPEG_ROW_COMPLETED;
+  return JPEG_SCAN_COMPLETED;
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+
+
+/*
+ * Initialize difference buffer controller.
+ */
+
+GLOBAL(void)
+jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  d_diff_ptr diff;
+  int ci;
+  jpeg_component_info *compptr;
+
+  diff = (d_diff_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(d_diff_controller));
+  losslsd->diff_private = (void *) diff;
+  losslsd->diff_start_input_pass = start_input_pass;
+  losslsd->pub.start_output_pass = start_output_pass;
+
+  /* Create the [un]difference buffers. */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    diff->diff_buf[ci] = (*cinfo->mem->alloc_darray)
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+            (long) compptr->h_samp_factor),
+       (JDIMENSION) compptr->v_samp_factor);
+    diff->undiff_buf[ci] = (*cinfo->mem->alloc_darray)
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+            (long) compptr->h_samp_factor),
+       (JDIMENSION) compptr->v_samp_factor);
+  }
+
+  if (need_full_buffer) {
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+    /* Allocate a full-image virtual array for each component. */
+    int access_rows;
+
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      access_rows = compptr->v_samp_factor;
+      diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
+  ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+   (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+        (long) compptr->h_samp_factor),
+   (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+        (long) compptr->v_samp_factor),
+   (JDIMENSION) access_rows);
+    }
+    losslsd->pub.consume_data = consume_data;
+    losslsd->pub.decompress_data = output_data;
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+  } else {
+    losslsd->pub.consume_data = dummy_consume_data;
+    losslsd->pub.decompress_data = decompress_data;
+    diff->whole_image[0] = NULL; /* flag for no virtual arrays */
+  }
+}
+
+#endif /* D_LOSSLESS_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdhuff.c b/Utilities/ITK/Utilities/itkjpeg/jdhuff.c
new file mode 100644
index 0000000000000000000000000000000000000000..54a827241c740c36fa3de1bf2eedded042d05747
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdhuff.c
@@ -0,0 +1,321 @@
+/*
+ * jdhuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines which are shared
+ * by the sequential, progressive and lossless decoders.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"    /* Private declarations for lossy codec */
+#include "jlossls.h"    /* Private declarations for lossless codec */
+#include "jdhuff.h"    /* Declarations shared with jd*huff.c */
+
+
+/*
+ * Compute the derived values for a Huffman table.
+ * This routine also performs some validation checks on the table.
+ */
+
+GLOBAL(void)
+jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
+       d_derived_tbl ** pdtbl)
+{
+  JHUFF_TBL *htbl;
+  d_derived_tbl *dtbl;
+  int p, i, l, si, numsymbols;
+  int lookbits, ctr;
+  char huffsize[257];
+  unsigned int huffcode[257];
+  unsigned int code;
+
+  /* Note that huffsize[] and huffcode[] are filled in code-length order,
+   * paralleling the order of the symbols themselves in htbl->huffval[].
+   */
+
+  /* Find the input Huffman table */
+  if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
+    ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+  htbl =
+    isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
+  if (htbl == NULL)
+    ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+
+  /* Allocate a workspace if we haven't already done so. */
+  if (*pdtbl == NULL)
+    *pdtbl = (d_derived_tbl *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          SIZEOF(d_derived_tbl));
+  dtbl = *pdtbl;
+  dtbl->pub = htbl;    /* fill in back link */
+  
+  /* Figure C.1: make table of Huffman code length for each symbol */
+
+  p = 0;
+  for (l = 1; l <= 16; l++) {
+    i = (int) htbl->bits[l];
+    if (i < 0 || p + i > 256)  /* protect against table overrun */
+      ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+    while (i--)
+      huffsize[p++] = (char) l;
+  }
+  huffsize[p] = 0;
+  numsymbols = p;
+  
+  /* Figure C.2: generate the codes themselves */
+  /* We also validate that the counts represent a legal Huffman code tree. */
+  
+  code = 0;
+  si = huffsize[0];
+  p = 0;
+  while (huffsize[p]) {
+    while (((int) huffsize[p]) == si) {
+      huffcode[p++] = code;
+      code++;
+    }
+    /* code is now 1 more than the last code used for codelength si; but
+     * it must still fit in si bits, since no code is allowed to be all ones.
+     * BUG FIX 2001-09-03: Comparison must be >, not >=
+     */
+    if (((INT32) code) > (((INT32) 1) << si))
+      ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+    code <<= 1;
+    si++;
+  }
+
+  /* Figure F.15: generate decoding tables for bit-sequential decoding */
+
+  p = 0;
+  for (l = 1; l <= 16; l++) {
+    if (htbl->bits[l]) {
+      /* valoffset[l] = huffval[] index of 1st symbol of code length l,
+       * minus the minimum code of length l
+       */
+      dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p];
+      p += htbl->bits[l];
+      dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
+    } else {
+      dtbl->maxcode[l] = -1;  /* -1 if no codes of this length */
+    }
+  }
+  dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */
+
+  /* Compute lookahead tables to speed up decoding.
+   * First we set all the table entries to 0, indicating "too long";
+   * then we iterate through the Huffman codes that are short enough and
+   * fill in all the entries that correspond to bit sequences starting
+   * with that code.
+   */
+
+  MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits));
+
+  p = 0;
+  for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
+    for (i = 1; i <= (int) htbl->bits[l]; i++, p++) {
+      /* l = current code's length, p = its index in huffcode[] & huffval[]. */
+      /* Generate left-justified code followed by all possible bit sequences */
+      lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
+      for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
+  dtbl->look_nbits[lookbits] = l;
+  dtbl->look_sym[lookbits] = htbl->huffval[p];
+  lookbits++;
+      }
+    }
+  }
+
+  /* Validate symbols as being reasonable.
+   * For AC tables, we make no check, but accept all byte values 0..255.
+   * For DC tables, we require the symbols to be in range 0..16.
+   * (Tighter bounds could be applied depending on the data depth and mode,
+   * but this is sufficient to ensure safe decoding.)
+   */
+  if (isDC) {
+    for (i = 0; i < numsymbols; i++) {
+      int sym = htbl->huffval[i];
+      if (sym < 0 || sym > 16)
+/* The following is needed to be able to read certain Philips DICOM MRI images */
+#if BITS_IN_JSAMPLE == 12
+        htbl->huffval[i]=15;
+#else
+  ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+#endif /* BITS_IN_JSAMPLE == 12 */
+    }
+  }
+}
+
+
+/*
+ * Out-of-line code for bit fetching.
+ * See jdhuff.h for info about usage.
+ * Note: current values of get_buffer and bits_left are passed as parameters,
+ * but are returned in the corresponding fields of the state struct.
+ *
+ * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
+ * of get_buffer to be used.  (On machines with wider words, an even larger
+ * buffer could be used.)  However, on some machines 32-bit shifts are
+ * quite slow and take time proportional to the number of places shifted.
+ * (This is true with most PC compilers, for instance.)  In this case it may
+ * be a win to set MIN_GET_BITS to the minimum value of 15.  This reduces the
+ * average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
+ */
+
+#ifdef SLOW_SHIFT_32
+#define MIN_GET_BITS  15  /* minimum allowable value */
+#else
+#define MIN_GET_BITS  (BIT_BUF_SIZE-7)
+#endif
+
+
+GLOBAL(boolean)
+jpeg_fill_bit_buffer (bitread_working_state * state,
+          register bit_buf_type get_buffer, register int bits_left,
+          int nbits)
+/* Load up the bit buffer to a depth of at least nbits */
+{
+  /* Copy heavily used state fields into locals (hopefully registers) */
+  register const JOCTET * next_input_byte = state->next_input_byte;
+  register size_t bytes_in_buffer = state->bytes_in_buffer;
+  j_decompress_ptr cinfo = state->cinfo;
+
+  /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
+  /* (It is assumed that no request will be for more than that many bits.) */
+  /* We fail to do so only if we hit a marker or are forced to suspend. */
+
+  if (cinfo->unread_marker == 0) {  /* cannot advance past a marker */
+    while (bits_left < MIN_GET_BITS) {
+      register int c;
+
+      /* Attempt to read a byte */
+      if (bytes_in_buffer == 0) {
+  if (! (*cinfo->src->fill_input_buffer) (cinfo))
+    return FALSE;
+  next_input_byte = cinfo->src->next_input_byte;
+  bytes_in_buffer = cinfo->src->bytes_in_buffer;
+      }
+      bytes_in_buffer--;
+      c = GETJOCTET(*next_input_byte++);
+
+      /* If it's 0xFF, check and discard stuffed zero byte */
+      if (c == 0xFF) {
+  /* Loop here to discard any padding FF's on terminating marker,
+   * so that we can save a valid unread_marker value.  NOTE: we will
+   * accept multiple FF's followed by a 0 as meaning a single FF data
+   * byte.  This data pattern is not valid according to the standard.
+   */
+  do {
+    if (bytes_in_buffer == 0) {
+      if (! (*cinfo->src->fill_input_buffer) (cinfo))
+        return FALSE;
+      next_input_byte = cinfo->src->next_input_byte;
+      bytes_in_buffer = cinfo->src->bytes_in_buffer;
+    }
+    bytes_in_buffer--;
+    c = GETJOCTET(*next_input_byte++);
+  } while (c == 0xFF);
+
+  if (c == 0) {
+    /* Found FF/00, which represents an FF data byte */
+    c = 0xFF;
+  } else {
+    /* Oops, it's actually a marker indicating end of compressed data.
+     * Save the marker code for later use.
+     * Fine point: it might appear that we should save the marker into
+     * bitread working state, not straight into permanent state.  But
+     * once we have hit a marker, we cannot need to suspend within the
+     * current MCU, because we will read no more bytes from the data
+     * source.  So it is OK to update permanent state right away.
+     */
+    cinfo->unread_marker = c;
+    /* See if we need to insert some fake zero bits. */
+    goto no_more_bytes;
+  }
+      }
+
+      /* OK, load c into get_buffer */
+      get_buffer = (get_buffer << 8) | c;
+      bits_left += 8;
+    } /* end while */
+  } else {
+  no_more_bytes:
+    /* We get here if we've read the marker that terminates the compressed
+     * data segment.  There should be enough bits in the buffer register
+     * to satisfy the request; if so, no problem.
+     */
+    if (nbits > bits_left) {
+      /* Uh-oh.  Report corrupted data to user and stuff zeroes into
+       * the data stream, so that we can produce some kind of image.
+       * We use a nonvolatile flag to ensure that only one warning message
+       * appears per data segment.
+       */
+      huffd_common_ptr huffd;
+      if (cinfo->process == JPROC_LOSSLESS)
+  huffd = (huffd_common_ptr) ((j_lossless_d_ptr) cinfo->codec)->entropy_private;
+      else
+  huffd = (huffd_common_ptr) ((j_lossy_d_ptr) cinfo->codec)->entropy_private;
+      if (! huffd->insufficient_data) {
+  WARNMS(cinfo, JWRN_HIT_MARKER);
+  huffd->insufficient_data = TRUE;
+      }
+      /* Fill the buffer with zero bits */
+      get_buffer <<= MIN_GET_BITS - bits_left;
+      bits_left = MIN_GET_BITS;
+    }
+  }
+
+  /* Unload the local registers */
+  state->next_input_byte = next_input_byte;
+  state->bytes_in_buffer = bytes_in_buffer;
+  state->get_buffer = get_buffer;
+  state->bits_left = bits_left;
+
+  return TRUE;
+}
+
+
+/*
+ * Out-of-line code for Huffman code decoding.
+ * See jdhuff.h for info about usage.
+ */
+
+GLOBAL(int)
+jpeg_huff_decode (bitread_working_state * state,
+      register bit_buf_type get_buffer, register int bits_left,
+      d_derived_tbl * htbl, int min_bits)
+{
+  register int l = min_bits;
+  register INT32 code;
+
+  /* HUFF_DECODE has determined that the code is at least min_bits */
+  /* bits long, so fetch that many bits in one swoop. */
+
+  CHECK_BIT_BUFFER(*state, l, return -1);
+  code = GET_BITS(l);
+
+  /* Collect the rest of the Huffman code one bit at a time. */
+  /* This is per Figure F.16 in the JPEG spec. */
+
+  while (code > htbl->maxcode[l]) {
+    code <<= 1;
+    CHECK_BIT_BUFFER(*state, 1, return -1);
+    code |= GET_BITS(1);
+    l++;
+  }
+
+  /* Unload the local registers */
+  state->get_buffer = get_buffer;
+  state->bits_left = bits_left;
+
+  /* With garbage input we may reach the sentinel value l = 17. */
+
+  if (l > 16) {
+    WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE);
+    return 0;      /* fake a zero as the safest result */
+  }
+
+  return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ];
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdhuff.h b/Utilities/ITK/Utilities/itkjpeg/jdhuff.h
new file mode 100644
index 0000000000000000000000000000000000000000..907465628a0fc9f20b6a00c44702016d4101e4d7
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdhuff.h
@@ -0,0 +1,229 @@
+/*
+ * jdhuff.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains declarations for Huffman entropy decoding routines
+ * that are shared between the sequential decoder (jdhuff.c), the
+ * progressive decoder (jdphuff.c) and the lossless decoder (jdlhuff.c).
+ * No other modules need to see these.
+ */
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_make_d_derived_tbl  jMkDDerived
+#define jpeg_fill_bit_buffer  jFilBitBuf
+#define jpeg_huff_decode  jHufDecode
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Derived data constructed for each Huffman table */
+
+#define HUFF_LOOKAHEAD  8  /* # of bits of lookahead */
+
+typedef struct {
+  /* Basic tables: (element [0] of each array is unused) */
+  INT32 maxcode[18];    /* largest code of length k (-1 if none) */
+  /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
+  INT32 valoffset[17];    /* huffval[] offset for codes of length k */
+  /* valoffset[k] = huffval[] index of 1st symbol of code length k, less
+   * the smallest code of length k; so given a code of length k, the
+   * corresponding symbol is huffval[code + valoffset[k]]
+   */
+
+  /* Link to public Huffman table (needed only in jpeg_huff_decode) */
+  JHUFF_TBL *pub;
+
+  /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
+   * the input data stream.  If the next Huffman code is no more
+   * than HUFF_LOOKAHEAD bits long, we can obtain its length and
+   * the corresponding symbol directly from these tables.
+   */
+  int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
+  UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
+} d_derived_tbl;
+
+/* Expand a Huffman table definition into the derived format */
+EXTERN(void) jpeg_make_d_derived_tbl
+  JPP((j_decompress_ptr cinfo, boolean isDC, int tblno,
+       d_derived_tbl ** pdtbl));
+
+
+/*
+ * Fetching the next N bits from the input stream is a time-critical operation
+ * for the Huffman decoders.  We implement it with a combination of inline
+ * macros and out-of-line subroutines.  Note that N (the number of bits
+ * demanded at one time) never exceeds 15 for JPEG use.
+ *
+ * We read source bytes into get_buffer and dole out bits as needed.
+ * If get_buffer already contains enough bits, they are fetched in-line
+ * by the macros CHECK_BIT_BUFFER and GET_BITS.  When there aren't enough
+ * bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer
+ * as full as possible (not just to the number of bits needed; this
+ * prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer).
+ * Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension.
+ * On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains
+ * at least the requested number of bits --- dummy zeroes are inserted if
+ * necessary.
+ */
+
+typedef INT32 bit_buf_type;  /* type of bit-extraction buffer */
+#define BIT_BUF_SIZE  32  /* size of buffer in bits */
+
+/* If long is > 32 bits on your machine, and shifting/masking longs is
+ * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE
+ * appropriately should be a win.  Unfortunately we can't define the size
+ * with something like  #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8)
+ * because not all machines measure sizeof in 8-bit bytes.
+ */
+
+typedef struct {    /* Bitreading state saved across MCUs */
+  bit_buf_type get_buffer;  /* current bit-extraction buffer */
+  int bits_left;    /* # of unused bits in it */
+} bitread_perm_state;
+
+typedef struct {    /* Bitreading working state within an MCU */
+  /* Current data source location */
+  /* We need a copy, rather than munging the original, in case of suspension */
+  const JOCTET * next_input_byte; /* => next byte to read from source */
+  size_t bytes_in_buffer;  /* # of bytes remaining in source buffer */
+  /* Bit input buffer --- note these values are kept in register variables,
+   * not in this struct, inside the inner loops.
+   */
+  bit_buf_type get_buffer;  /* current bit-extraction buffer */
+  int bits_left;    /* # of unused bits in it */
+  /* Pointer needed by jpeg_fill_bit_buffer. */
+  j_decompress_ptr cinfo;  /* back link to decompress master record */
+} bitread_working_state;
+
+/* Macros to declare and load/save bitread local variables. */
+#define BITREAD_STATE_VARS  \
+  register bit_buf_type get_buffer;  \
+  register int bits_left;  \
+  bitread_working_state br_state
+
+#define BITREAD_LOAD_STATE(cinfop,permstate)  \
+  br_state.cinfo = cinfop; \
+  br_state.next_input_byte = cinfop->src->next_input_byte; \
+  br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
+  get_buffer = permstate.get_buffer; \
+  bits_left = permstate.bits_left;
+
+#define BITREAD_SAVE_STATE(cinfop,permstate)  \
+  cinfop->src->next_input_byte = br_state.next_input_byte; \
+  cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
+  permstate.get_buffer = get_buffer; \
+  permstate.bits_left = bits_left
+
+/*
+ * These macros provide the in-line portion of bit fetching.
+ * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
+ * before using GET_BITS, PEEK_BITS, or DROP_BITS.
+ * The variables get_buffer and bits_left are assumed to be locals,
+ * but the state struct might not be (jpeg_huff_decode needs this).
+ *  CHECK_BIT_BUFFER(state,n,action);
+ *    Ensure there are N bits in get_buffer; if suspend, take action.
+ *      val = GET_BITS(n);
+ *    Fetch next N bits.
+ *      val = PEEK_BITS(n);
+ *    Fetch next N bits without removing them from the buffer.
+ *  DROP_BITS(n);
+ *    Discard next N bits.
+ * The value N should be a simple variable, not an expression, because it
+ * is evaluated multiple times.
+ */
+
+#define CHECK_BIT_BUFFER(state,nbits,action) \
+  { if (bits_left < (nbits)) {  \
+      if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits))  \
+        { action; }  \
+      get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
+
+#define GET_BITS(nbits) \
+  (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
+
+#define PEEK_BITS(nbits) \
+  (((int) (get_buffer >> (bits_left -  (nbits)))) & ((1<<(nbits))-1))
+
+#define DROP_BITS(nbits) \
+  (bits_left -= (nbits))
+
+/* Load up the bit buffer to a depth of at least nbits */
+EXTERN(boolean) jpeg_fill_bit_buffer
+  JPP((bitread_working_state * state, register bit_buf_type get_buffer,
+       register int bits_left, int nbits));
+
+
+/*
+ * Code for extracting next Huffman-coded symbol from input bit stream.
+ * Again, this is time-critical and we make the main paths be macros.
+ *
+ * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
+ * without looping.  Usually, more than 95% of the Huffman codes will be 8
+ * or fewer bits long.  The few overlength codes are handled with a loop,
+ * which need not be inline code.
+ *
+ * Notes about the HUFF_DECODE macro:
+ * 1. Near the end of the data segment, we may fail to get enough bits
+ *    for a lookahead.  In that case, we do it the hard way.
+ * 2. If the lookahead table contains no entry, the next code must be
+ *    more than HUFF_LOOKAHEAD bits long.
+ * 3. jpeg_huff_decode returns -1 if forced to suspend.
+ */
+
+#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \
+{ register int nb, look; \
+  if (bits_left < HUFF_LOOKAHEAD) { \
+    if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \
+    get_buffer = state.get_buffer; bits_left = state.bits_left; \
+    if (bits_left < HUFF_LOOKAHEAD) { \
+      nb = 1; goto slowlabel; \
+    } \
+  } \
+  look = PEEK_BITS(HUFF_LOOKAHEAD); \
+  if ((nb = htbl->look_nbits[look]) != 0) { \
+    DROP_BITS(nb); \
+    result = htbl->look_sym[look]; \
+  } else { \
+    nb = HUFF_LOOKAHEAD+1; \
+slowlabel: \
+    if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
+  { failaction; } \
+    get_buffer = state.get_buffer; bits_left = state.bits_left; \
+  } \
+}
+
+/* Out-of-line case for Huffman code fetching */
+EXTERN(int) jpeg_huff_decode
+  JPP((bitread_working_state * state, register bit_buf_type get_buffer,
+       register int bits_left, d_derived_tbl * htbl, int min_bits));
+
+
+/* Common fields between sequential, progressive and lossless Huffman entropy
+ * decoder master structs.
+ */
+
+#define huffd_common_fields \
+  boolean insufficient_data;  /* set TRUE after emmitting warning */ \
+  /* These fields are loaded into local variables at start of each MCU. \
+   * In case of suspension, we exit WITHOUT updating them. \
+   */ \
+  bitread_perm_state bitstate  /* Bit buffer at start of MCU */
+
+/* Routines that are to be used by any or all of the entropy decoders are
+ * declared to receive a pointer to this structure.  There are no actual
+ * instances of huffd_common_struct, only of shuff_entropy_decoder,
+ * phuff_entropy_decoder and lhuff_entropy_decoder.
+ */
+struct huffd_common_struct {
+  huffd_common_fields;    /* Fields common to all decoder struct types */
+  /* Additional fields follow in an actual shuff_entropy_decoder,
+   * phuff_entropy_decoder or lhuff_entropy_decoder struct.  All four structs
+   * must agree on these initial fields!  (This would be a lot cleaner in C++.)
+   */
+};
+
+typedef struct huffd_common_struct * huffd_common_ptr;
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdinput.c b/Utilities/ITK/Utilities/itkjpeg/jdinput.c
new file mode 100644
index 0000000000000000000000000000000000000000..8cb0f22d81d0aa205451b74bfbc2679fed9b3fee
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdinput.c
@@ -0,0 +1,347 @@
+/*
+ * jdinput.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains input control logic for the JPEG decompressor.
+ * These routines are concerned with controlling the decompressor's input
+ * processing (marker reading and coefficient/difference decoding).
+ * The actual input reading is done in jdmarker.c, jdhuff.c, jdphuff.c,
+ * and jdlhuff.c.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private state */
+
+typedef struct {
+  struct jpeg_input_controller pub; /* public fields */
+
+  boolean inheaders;    /* TRUE until first SOS is reached */
+} my_input_controller;
+
+typedef my_input_controller * my_inputctl_ptr;
+
+
+/* Forward declarations */
+METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Routines to calculate various quantities related to the size of the image.
+ */
+
+LOCAL(void)
+initial_setup (j_decompress_ptr cinfo)
+/* Called once, when first SOS marker is reached */
+{
+  int ci;
+  jpeg_component_info *compptr;
+
+  /* Make sure image isn't bigger than I can handle */
+  if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
+      (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
+    ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+
+  if (cinfo->process == JPROC_LOSSLESS) {
+    /* If precision > compiled-in value, we must downscale */
+    if (cinfo->data_precision > BITS_IN_JSAMPLE)
+      WARNMS2(cinfo, JWRN_MUST_DOWNSCALE,
+        cinfo->data_precision, BITS_IN_JSAMPLE);
+  }
+  else {  /* Lossy processes */
+    /* For now, precision must match compiled-in value... */
+    if (cinfo->data_precision != BITS_IN_JSAMPLE)
+      ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
+  }
+
+  /* Check that number of components won't exceed internal array sizes */
+  if (cinfo->num_components > MAX_COMPONENTS)
+    ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+       MAX_COMPONENTS);
+
+  /* Compute maximum sampling factors; check factor validity */
+  cinfo->max_h_samp_factor = 1;
+  cinfo->max_v_samp_factor = 1;
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
+  compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+      ERREXIT(cinfo, JERR_BAD_SAMPLING);
+    cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
+           compptr->h_samp_factor);
+    cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
+           compptr->v_samp_factor);
+  }
+
+  /* We initialize codec_data_unit and min_codec_data_unit to data_unit.
+   * In the full decompressor, this will be overridden by jdmaster.c;
+   * but in the transcoder, jdmaster.c is not used, so we must do it here.
+   */
+  cinfo->min_codec_data_unit = cinfo->data_unit;
+
+  /* Compute dimensions of components */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    compptr->codec_data_unit = cinfo->data_unit;
+    /* Size in data units */
+    compptr->width_in_data_units = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+        (long) (cinfo->max_h_samp_factor * cinfo->data_unit));
+    compptr->height_in_data_units = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+        (long) (cinfo->max_v_samp_factor * cinfo->data_unit));
+    /* downsampled_width and downsampled_height will also be overridden by
+     * jdmaster.c if we are doing full decompression.  The transcoder library
+     * doesn't use these values, but the calling application might.
+     */
+    /* Size in samples */
+    compptr->downsampled_width = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+        (long) cinfo->max_h_samp_factor);
+    compptr->downsampled_height = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+        (long) cinfo->max_v_samp_factor);
+    /* Mark component needed, until color conversion says otherwise */
+    compptr->component_needed = TRUE;
+    /* Mark no quantization table yet saved for component */
+    compptr->quant_table = NULL;
+  }
+
+  /* Compute number of fully interleaved MCU rows. */
+  cinfo->total_iMCU_rows = (JDIMENSION)
+    jdiv_round_up((long) cinfo->image_height,
+      (long) (cinfo->max_v_samp_factor*cinfo->data_unit));
+
+  /* Decide whether file contains multiple scans */
+  if (cinfo->comps_in_scan < cinfo->num_components ||
+      cinfo->process == JPROC_PROGRESSIVE)
+    cinfo->inputctl->has_multiple_scans = TRUE;
+  else
+    cinfo->inputctl->has_multiple_scans = FALSE;
+}
+
+
+LOCAL(void)
+per_scan_setup (j_decompress_ptr cinfo)
+/* Do computations that are needed before processing a JPEG scan */
+/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
+{
+  int ci, mcublks, tmp;
+  jpeg_component_info *compptr;
+
+  if (cinfo->comps_in_scan == 1) {
+    
+    /* Noninterleaved (single-component) scan */
+    compptr = cinfo->cur_comp_info[0];
+    
+    /* Overall image size in MCUs */
+    cinfo->MCUs_per_row = compptr->width_in_data_units;
+    cinfo->MCU_rows_in_scan = compptr->height_in_data_units;
+    
+    /* For noninterleaved scan, always one data unit per MCU */
+    compptr->MCU_width = 1;
+    compptr->MCU_height = 1;
+    compptr->MCU_data_units = 1;
+    compptr->MCU_sample_width = compptr->codec_data_unit;
+    compptr->last_col_width = 1;
+    /* For noninterleaved scans, it is convenient to define last_row_height
+     * as the number of data unit rows present in the last iMCU row.
+     */
+    tmp = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+    if (tmp == 0) tmp = compptr->v_samp_factor;
+    compptr->last_row_height = tmp;
+    
+    /* Prepare array describing MCU composition */
+    cinfo->data_units_in_MCU = 1;
+    cinfo->MCU_membership[0] = 0;
+    
+  } else {
+    
+    /* Interleaved (multi-component) scan */
+    if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
+      ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
+         MAX_COMPS_IN_SCAN);
+    
+    /* Overall image size in MCUs */
+    cinfo->MCUs_per_row = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_width,
+        (long) (cinfo->max_h_samp_factor*cinfo->data_unit));
+    cinfo->MCU_rows_in_scan = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_height,
+        (long) (cinfo->max_v_samp_factor*cinfo->data_unit));
+    
+    cinfo->data_units_in_MCU = 0;
+    
+    for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+      compptr = cinfo->cur_comp_info[ci];
+      /* Sampling factors give # of data units of component in each MCU */
+      compptr->MCU_width = compptr->h_samp_factor;
+      compptr->MCU_height = compptr->v_samp_factor;
+      compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height;
+      compptr->MCU_sample_width = compptr->MCU_width * compptr->codec_data_unit;
+      /* Figure number of non-dummy data units in last MCU column & row */
+      tmp = (int) (compptr->width_in_data_units % compptr->MCU_width);
+      if (tmp == 0) tmp = compptr->MCU_width;
+      compptr->last_col_width = tmp;
+      tmp = (int) (compptr->height_in_data_units % compptr->MCU_height);
+      if (tmp == 0) tmp = compptr->MCU_height;
+      compptr->last_row_height = tmp;
+      /* Prepare array describing MCU composition */
+      mcublks = compptr->MCU_data_units;
+      if (cinfo->data_units_in_MCU + mcublks > D_MAX_DATA_UNITS_IN_MCU)
+  ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
+      while (mcublks-- > 0) {
+  cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci;
+      }
+    }
+    
+  }
+}
+
+
+/*
+ * Initialize the input modules to read a scan of compressed data.
+ * The first call to this is done by jdmaster.c after initializing
+ * the entire decompressor (during jpeg_start_decompress).
+ * Subsequent calls come from consume_markers, below.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+  per_scan_setup(cinfo);
+  (*cinfo->codec->start_input_pass) (cinfo);
+  cinfo->inputctl->consume_input = cinfo->codec->consume_data;
+}
+
+
+/*
+ * Finish up after inputting a compressed-data scan.
+ * This is called by the coefficient controller after it's read all
+ * the expected data of the scan.
+ */
+
+METHODDEF(void)
+finish_input_pass (j_decompress_ptr cinfo)
+{
+  cinfo->inputctl->consume_input = consume_markers;
+}
+
+
+/*
+ * Read JPEG markers before, between, or after compressed-data scans.
+ * Change state as necessary when a new scan is reached.
+ * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ *
+ * The consume_input method pointer points either here or to the
+ * coefficient controller's consume_data routine, depending on whether
+ * we are reading a compressed data segment or inter-segment markers.
+ */
+
+METHODDEF(int)
+consume_markers (j_decompress_ptr cinfo)
+{
+  my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+  int val;
+
+  if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
+    return JPEG_REACHED_EOI;
+
+  val = (*cinfo->marker->read_markers) (cinfo);
+
+  switch (val) {
+  case JPEG_REACHED_SOS:  /* Found SOS */
+    if (inputctl->inheaders) {  /* 1st SOS */
+      initial_setup(cinfo);
+      /*
+       * Initialize the decompression codec.  We need to do this here so that
+       * any codec-specific fields and function pointers are available to
+       * the rest of the library.
+       */
+      jinit_d_codec(cinfo);
+      inputctl->inheaders = FALSE;
+      /* Note: start_input_pass must be called by jdmaster.c
+       * before any more input can be consumed.  jdapimin.c is
+       * responsible for enforcing this sequencing.
+       */
+    } else {      /* 2nd or later SOS marker */
+      if (! inputctl->pub.has_multiple_scans)
+  ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
+      start_input_pass(cinfo);
+    }
+    break;
+  case JPEG_REACHED_EOI:  /* Found EOI */
+    inputctl->pub.eoi_reached = TRUE;
+    if (inputctl->inheaders) {  /* Tables-only datastream, apparently */
+      if (cinfo->marker->saw_SOF)
+  ERREXIT(cinfo, JERR_SOF_NO_SOS);
+    } else {
+      /* Prevent infinite loop in coef ctlr's decompress_data routine
+       * if user set output_scan_number larger than number of scans.
+       */
+      if (cinfo->output_scan_number > cinfo->input_scan_number)
+  cinfo->output_scan_number = cinfo->input_scan_number;
+    }
+    break;
+  case JPEG_SUSPENDED:
+    break;
+  }
+
+  return val;
+}
+
+
+/*
+ * Reset state to begin a fresh datastream.
+ */
+
+METHODDEF(void)
+reset_input_controller (j_decompress_ptr cinfo)
+{
+  my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+
+  inputctl->pub.consume_input = consume_markers;
+  inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
+  inputctl->pub.eoi_reached = FALSE;
+  inputctl->inheaders = TRUE;
+  /* Reset other modules */
+  (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+  (*cinfo->marker->reset_marker_reader) (cinfo);
+  /* Reset progression state -- would be cleaner if entropy decoder did this */
+  cinfo->coef_bits = NULL;
+}
+
+
+/*
+ * Initialize the input controller module.
+ * This is called only once, when the decompression object is created.
+ */
+
+GLOBAL(void)
+jinit_input_controller (j_decompress_ptr cinfo)
+{
+  my_inputctl_ptr inputctl;
+
+  /* Create subobject in permanent pool */
+  inputctl = (my_inputctl_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+        SIZEOF(my_input_controller));
+  cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
+  /* Initialize method pointers */
+  inputctl->pub.consume_input = consume_markers;
+  inputctl->pub.reset_input_controller = reset_input_controller;
+  inputctl->pub.start_input_pass = start_input_pass;
+  inputctl->pub.finish_input_pass = finish_input_pass;
+  /* Initialize state: can't use reset_input_controller since we don't
+   * want to try to reset other modules yet.
+   */
+  inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
+  inputctl->pub.eoi_reached = FALSE;
+  inputctl->inheaders = TRUE;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdlhuff.c b/Utilities/ITK/Utilities/itkjpeg/jdlhuff.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ee9f28a6108b5ee344bb50b6d1ffd333ba33013
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdlhuff.c
@@ -0,0 +1,291 @@
+/*
+ * jdlhuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines for lossless JPEG.
+ *
+ * Much of the complexity here has to do with supporting input suspension.
+ * If the data source module demands suspension, we want to be able to back
+ * up to the start of the current MCU.  To do this, we copy state variables
+ * into local working storage, and update them back to the permanent
+ * storage only upon successful completion of an MCU.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossls.h"    /* Private declarations for lossless codec */
+#include "jdhuff.h"    /* Declarations shared with jd*huff.c */
+
+
+#ifdef D_LOSSLESS_SUPPORTED
+
+typedef struct {
+  int ci, yoffset, MCU_width;
+} lhd_output_ptr_info;
+
+/*
+ * Private entropy decoder object for lossless Huffman decoding.
+ */
+
+typedef struct {
+  huffd_common_fields;    /* Fields shared with other entropy decoders */
+
+  /* Pointers to derived tables (these workspaces have image lifespan) */
+  d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+  /* Precalculated info set up by start_pass for use in decode_mcus: */
+
+  /* Pointers to derived tables to be used for each data unit within an MCU */
+  d_derived_tbl * cur_tbls[D_MAX_DATA_UNITS_IN_MCU];
+
+  /* Pointers to the proper output difference row for each group of data units
+   * within an MCU.  For each component, there are Vi groups of Hi data units.
+   */
+  JDIFFROW output_ptr[D_MAX_DATA_UNITS_IN_MCU];
+
+  /* Number of output pointers in use for the current MCU.  This is the sum
+   * of all Vi in the MCU.
+   */
+  int num_output_ptrs;
+
+  /* Information used for positioning the output pointers within the output
+   * difference rows.
+   */
+  lhd_output_ptr_info output_ptr_info[D_MAX_DATA_UNITS_IN_MCU];
+
+  /* Index of the proper output pointer for each data unit within an MCU */
+  int output_ptr_index[D_MAX_DATA_UNITS_IN_MCU];
+
+} lhuff_entropy_decoder;
+
+typedef lhuff_entropy_decoder * lhuff_entropy_ptr;
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass_lhuff_decoder (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
+  int ci, dctbl, sampn, ptrn, yoffset, xoffset;
+  jpeg_component_info * compptr;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    dctbl = compptr->dc_tbl_no;
+    /* Make sure requested tables are present */
+    if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS ||
+  cinfo->dc_huff_tbl_ptrs[dctbl] == NULL)
+      ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
+    /* Compute derived values for Huffman tables */
+    /* We may do this more than once for a table, but it's not expensive */
+    jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
+          & entropy->derived_tbls[dctbl]);
+  }
+
+  /* Precalculate decoding info for each sample in an MCU of this scan */
+  for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) {
+    compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]];
+    ci = compptr->component_index;
+    for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) {
+      /* Precalculate the setup info for each output pointer */
+      entropy->output_ptr_info[ptrn].ci = ci;
+      entropy->output_ptr_info[ptrn].yoffset = yoffset;
+      entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width;
+      for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) {
+  /* Precalculate the output pointer index for each sample */
+  entropy->output_ptr_index[sampn] = ptrn;
+  /* Precalculate which table to use for each sample */
+  entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no];
+      }
+    }
+  }
+  entropy->num_output_ptrs = ptrn;
+
+  /* Initialize bitread state variables */
+  entropy->bitstate.bits_left = 0;
+  entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+  entropy->insufficient_data = FALSE;
+}
+
+
+/*
+ * Figure F.12: extend sign bit.
+ * On some machines, a shift and add will be faster than a table lookup.
+ */
+
+#ifdef AVOID_TABLES
+
+#define HUFF_EXTEND(x,s)  ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
+
+#else
+
+#define HUFF_EXTEND(x,s)  ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+
+static const int extend_test[16] =   /* entry n is 2**(n-1) */
+  { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+    0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+
+static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
+  { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
+    ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
+    ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
+    ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+
+#endif /* AVOID_TABLES */
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ * Returns FALSE if must suspend.
+ */
+
+METHODDEF(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
+  /* int ci; */
+
+  /* Throw away any unused bits remaining in bit buffer; */
+  /* include any full bytes in next_marker's count of discarded bytes */
+  cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
+  entropy->bitstate.bits_left = 0;
+
+  /* Advance past the RSTn marker */
+  if (! (*cinfo->marker->read_restart_marker) (cinfo))
+    return FALSE;
+
+  /* Reset out-of-data flag, unless read_restart_marker left us smack up
+   * against a marker.  In that case we will end up treating the next data
+   * segment as empty, and we can avoid producing bogus output pixels by
+   * leaving the flag set.
+   */
+  if (cinfo->unread_marker == 0)
+    entropy->insufficient_data = FALSE;
+
+  return TRUE;
+}
+
+
+/*
+ * Decode and return nMCU's worth of Huffman-compressed differences.
+ * Each MCU is also disassembled and placed accordingly in diff_buf.
+ *
+ * MCU_col_num specifies the column of the first MCU being requested within
+ * the MCU-row.  This tells us where to position the output row pointers in
+ * diff_buf.
+ *
+ * Returns the number of MCUs decoded.  This may be less than nMCU if data
+ * source requested suspension.  In that case no changes have been made to
+ * permanent state.  (Exception: some output differences may already have
+ * been assigned.  This is harmless for this module, since we'll just
+ * re-assign them on the next call.)
+ */
+
+METHODDEF(JDIMENSION)
+decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf,
+       JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
+  unsigned int mcu_num;
+  int sampn, ci, yoffset, MCU_width, ptrn;
+  BITREAD_STATE_VARS;
+
+  /* Set output pointer locations based on MCU_col_num */
+  for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) {
+    ci = entropy->output_ptr_info[ptrn].ci;
+    yoffset = entropy->output_ptr_info[ptrn].yoffset;
+    MCU_width = entropy->output_ptr_info[ptrn].MCU_width;
+    entropy->output_ptr[ptrn] =
+      diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
+  }
+
+  /*
+   * If we've run out of data, zero out the buffers and return.
+   * By resetting the undifferencer, the output samples will be CENTERJSAMPLE.
+   *
+   * NB: We should find a way to do this without interacting with the
+   * undifferencer module directly.
+   */
+  if (entropy->insufficient_data) {
+    for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++)
+      jzero_far((void FAR *) entropy->output_ptr[ptrn],
+    nMCU * entropy->output_ptr_info[ptrn].MCU_width * SIZEOF(JDIFF));
+
+    (*losslsd->predict_process_restart) (cinfo);
+  }
+
+  else {
+
+    /* Load up working state */
+    BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+
+    /* Outer loop handles the number of MCU requested */
+
+    for (mcu_num = 0; mcu_num < nMCU; mcu_num++) {
+
+      /* Inner loop handles the samples in the MCU */
+      for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) {
+  d_derived_tbl * dctbl = entropy->cur_tbls[sampn];
+  register int s, r;
+
+  /* Section H.2.2: decode the sample difference */
+  HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1);
+  if (s) {
+    if (s == 16)  /* special case: always output 32768 */
+      s = 32768;
+    else {  /* normal case: fetch subsequent bits */
+      CHECK_BIT_BUFFER(br_state, s, return mcu_num);
+      r = GET_BITS(s);
+      s = HUFF_EXTEND(r, s);
+    }
+  }
+
+  /* Output the sample difference */
+  *entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF) s;
+      }
+
+      /* Completed MCU, so update state */
+      BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+    }
+  }
+
+ return nMCU;
+}
+
+
+/*
+ * Module initialization routine for lossless Huffman entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_lhuff_decoder (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  lhuff_entropy_ptr entropy;
+  int i;
+
+  entropy = (lhuff_entropy_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(lhuff_entropy_decoder));
+  losslsd->entropy_private = (void *) entropy;
+  losslsd->entropy_start_pass = start_pass_lhuff_decoder;
+  losslsd->entropy_process_restart = process_restart;
+  losslsd->entropy_decode_mcus = decode_mcus;
+
+  /* Mark tables unallocated */
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    entropy->derived_tbls[i] = NULL;
+  }
+}
+
+#endif /* D_LOSSLESS_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdlossls.c b/Utilities/ITK/Utilities/itkjpeg/jdlossls.c
new file mode 100644
index 0000000000000000000000000000000000000000..046cd3b729ad63d50d32a943b923c44d1f44bed7
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdlossls.c
@@ -0,0 +1,94 @@
+/*
+ * jdlossls.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the control logic for the lossless JPEG decompressor.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossls.h"
+
+
+#ifdef D_LOSSLESS_SUPPORTED
+
+/*
+ * Compute output image dimensions and related values.
+ */
+
+METHODDEF(void)
+calc_output_dimensions (j_decompress_ptr cinfo)
+{
+  /* Hardwire it to "no scaling" */
+  cinfo->output_width = cinfo->image_width;
+  cinfo->output_height = cinfo->image_height;
+  /* jdinput.c has already initialized codec_data_unit to 1,
+   * and has computed unscaled downsampled_width and downsampled_height.
+   */
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+
+  (*losslsd->entropy_start_pass) (cinfo);
+  (*losslsd->predict_start_pass) (cinfo);
+  (*losslsd->scaler_start_pass) (cinfo);
+  (*losslsd->diff_start_input_pass) (cinfo);
+}
+
+
+/*
+ * Initialize the lossless decompression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void) 
+jinit_lossless_d_codec(j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd;
+  boolean use_c_buffer;
+
+  /* Create subobject in permanent pool */
+  losslsd = (j_lossless_d_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+        SIZEOF(jpeg_lossless_d_codec));
+  cinfo->codec = (struct jpeg_d_codec *) losslsd;
+
+  /* Initialize sub-modules */
+  /* Entropy decoding: either Huffman or arithmetic coding. */
+  if (cinfo->arith_code) {
+    jinit_arith_decoder(cinfo);
+  } else {
+    jinit_lhuff_decoder(cinfo);
+  }
+
+  /* Undifferencer */
+  jinit_undifferencer(cinfo);
+
+  /* Scaler */
+  jinit_d_scaler(cinfo);
+
+  use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
+  jinit_d_diff_controller(cinfo, use_c_buffer);
+
+  /* Initialize method pointers.
+   *
+   * Note: consume_data, start_output_pass and decompress_data are
+   * assigned in jddiffct.c.
+   */
+  losslsd->pub.calc_output_dimensions = calc_output_dimensions;
+  losslsd->pub.start_input_pass = start_input_pass;
+}
+
+#endif /* D_LOSSLESS_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdlossy.c b/Utilities/ITK/Utilities/itkjpeg/jdlossy.c
new file mode 100644
index 0000000000000000000000000000000000000000..637714facf49cd0c8ac7a333aced907bd0d86ee6
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdlossy.c
@@ -0,0 +1,228 @@
+/*
+ * jdlossy.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the control logic for the lossy JPEG decompressor.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"
+
+
+/*
+ * Compute output image dimensions and related values.
+ */
+
+METHODDEF(void)
+calc_output_dimensions (j_decompress_ptr cinfo)
+{
+#ifdef IDCT_SCALING_SUPPORTED
+  int ci;
+  jpeg_component_info *compptr;
+
+  /* Compute actual output image dimensions and DCT scaling choices. */
+  if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
+    /* Provide 1/8 scaling */
+    cinfo->output_width = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_width, 8L);
+    cinfo->output_height = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_height, 8L);
+    cinfo->min_codec_data_unit = 1;
+  } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
+    /* Provide 1/4 scaling */
+    cinfo->output_width = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_width, 4L);
+    cinfo->output_height = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_height, 4L);
+    cinfo->min_codec_data_unit = 2;
+  } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
+    /* Provide 1/2 scaling */
+    cinfo->output_width = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_width, 2L);
+    cinfo->output_height = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_height, 2L);
+    cinfo->min_codec_data_unit = 4;
+  } else {
+    /* Provide 1/1 scaling */
+    cinfo->output_width = cinfo->image_width;
+    cinfo->output_height = cinfo->image_height;
+    cinfo->min_codec_data_unit = DCTSIZE;
+  }
+  /* In selecting the actual DCT scaling for each component, we try to
+   * scale up the chroma components via IDCT scaling rather than upsampling.
+   * This saves time if the upsampler gets to use 1:1 scaling.
+   * Note this code assumes that the supported DCT scalings are powers of 2.
+   */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    int ssize = cinfo->min_codec_data_unit;
+    while (ssize < DCTSIZE &&
+     (compptr->h_samp_factor * ssize * 2 <=
+      cinfo->max_h_samp_factor * cinfo->min_codec_data_unit) &&
+     (compptr->v_samp_factor * ssize * 2 <=
+      cinfo->max_v_samp_factor * cinfo->min_codec_data_unit)) {
+      ssize = ssize * 2;
+    }
+    compptr->codec_data_unit = ssize;
+  }
+
+  /* Recompute downsampled dimensions of components;
+   * application needs to know these if using raw downsampled data.
+   */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Size in samples, after IDCT scaling */
+    compptr->downsampled_width = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_width *
+        (long) (compptr->h_samp_factor * compptr->codec_data_unit),
+        (long) (cinfo->max_h_samp_factor * DCTSIZE));
+    compptr->downsampled_height = (JDIMENSION)
+      jdiv_round_up((long) cinfo->image_height *
+        (long) (compptr->v_samp_factor * compptr->codec_data_unit),
+        (long) (cinfo->max_v_samp_factor * DCTSIZE));
+  }
+
+#else /* !IDCT_SCALING_SUPPORTED */
+
+  /* Hardwire it to "no scaling" */
+  cinfo->output_width = cinfo->image_width;
+  cinfo->output_height = cinfo->image_height;
+  /* jdinput.c has already initialized codec_data_unit to DCTSIZE,
+   * and has computed unscaled downsampled_width and downsampled_height.
+   */
+
+#endif /* IDCT_SCALING_SUPPORTED */
+}
+
+
+/*
+ * Save away a copy of the Q-table referenced by each component present
+ * in the current scan, unless already saved during a prior scan.
+ *
+ * In a multiple-scan JPEG file, the encoder could assign different components
+ * the same Q-table slot number, but change table definitions between scans
+ * so that each component uses a different Q-table.  (The IJG encoder is not
+ * currently capable of doing this, but other encoders might.)  Since we want
+ * to be able to dequantize all the components at the end of the file, this
+ * means that we have to save away the table actually used for each component.
+ * We do this by copying the table at the start of the first scan containing
+ * the component.
+ * The JPEG spec prohibits the encoder from changing the contents of a Q-table
+ * slot between scans of a component using that slot.  If the encoder does so
+ * anyway, this decoder will simply use the Q-table values that were current
+ * at the start of the first scan for the component.
+ *
+ * The decompressor output side looks only at the saved quant tables,
+ * not at the current Q-table slots.
+ */
+
+LOCAL(void)
+latch_quant_tables (j_decompress_ptr cinfo)
+{
+  int ci, qtblno;
+  jpeg_component_info *compptr;
+  JQUANT_TBL * qtbl;
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    /* No work if we already saved Q-table for this component */
+    if (compptr->quant_table != NULL)
+      continue;
+    /* Make sure specified quantization table is present */
+    qtblno = compptr->quant_tbl_no;
+    if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
+  cinfo->quant_tbl_ptrs[qtblno] == NULL)
+      ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
+    /* OK, save away the quantization table */
+    qtbl = (JQUANT_TBL *)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          SIZEOF(JQUANT_TBL));
+    MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
+    compptr->quant_table = qtbl;
+  }
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+
+  latch_quant_tables(cinfo);
+  (*lossyd->entropy_start_pass) (cinfo);
+  (*lossyd->coef_start_input_pass) (cinfo);
+}
+
+
+/*
+ * Initialize for an output processing pass.
+ */
+
+METHODDEF(void)
+start_output_pass (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+
+  (*lossyd->idct_start_pass) (cinfo);
+  (*lossyd->coef_start_output_pass) (cinfo);
+}
+
+/*
+ * Initialize the lossy decompression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void)
+jinit_lossy_d_codec (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd;
+  boolean use_c_buffer;
+
+  /* Create subobject in permanent pool */
+  lossyd = (j_lossy_d_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+        SIZEOF(jpeg_lossy_d_codec));
+  cinfo->codec = (struct jpeg_d_codec *) lossyd;
+
+  /* Initialize sub-modules */
+
+  /* Inverse DCT */
+  jinit_inverse_dct(cinfo);
+  /* Entropy decoding: either Huffman or arithmetic coding. */
+  if (cinfo->arith_code) {
+    jinit_arith_decoder(cinfo);
+  } else {
+    if (cinfo->process == JPROC_PROGRESSIVE) {
+#ifdef D_PROGRESSIVE_SUPPORTED
+      jinit_phuff_decoder(cinfo);
+#else
+      ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+    } else
+      jinit_shuff_decoder(cinfo);
+  }
+
+  use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
+  jinit_d_coef_controller(cinfo, use_c_buffer);
+
+  /* Initialize method pointers.
+   *
+   * Note: consume_data and decompress_data are assigned in jdcoefct.c.
+   */
+  lossyd->pub.calc_output_dimensions = calc_output_dimensions;
+  lossyd->pub.start_input_pass = start_input_pass;
+  lossyd->pub.start_output_pass = start_output_pass;
+}
+
+
+
+
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdmainct.c b/Utilities/ITK/Utilities/itkjpeg/jdmainct.c
new file mode 100644
index 0000000000000000000000000000000000000000..43cb09b719e48f297974d8c8a1babbe797166741
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdmainct.c
@@ -0,0 +1,512 @@
+/*
+ * jdmainct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the main buffer controller for decompression.
+ * The main buffer lies between the JPEG decompressor proper and the
+ * post-processor; it holds downsampled data in the JPEG colorspace.
+ *
+ * Note that this code is bypassed in raw-data mode, since the application
+ * supplies the equivalent of the main buffer in that case.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * In the current system design, the main buffer need never be a full-image
+ * buffer; any full-height buffers will be found inside the coefficient or
+ * postprocessing controllers.  Nonetheless, the main controller is not
+ * trivial.  Its responsibility is to provide context rows for upsampling/
+ * rescaling, and doing this in an efficient fashion is a bit tricky.
+ *
+ * Postprocessor input data is counted in "row groups".  A row group
+ * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit)
+ * sample rows of each component.  (We require codec_data_unit values to be
+ * chosen such that these numbers are integers.  In practice codec_data_unit
+ * values will likely be powers of two, so we actually have the stronger
+ * condition that codec_data_unit / min_codec_data_unit is an integer.)
+ * Upsampling will typically produce max_v_samp_factor pixel rows from each
+ * row group (times any additional scale factor that the upsampler is
+ * applying).
+ *
+ * The decompression codec will deliver data to us one iMCU row at a time;
+ * each iMCU row contains v_samp_factor * codec_data_unit sample rows, or
+ * exactly min_codec_data_unit row groups.  (This amount of data corresponds
+ * to one row of MCUs when the image is fully interleaved.)  Note that the
+ * number of sample rows varies across components, but the number of row
+ * groups does not.  Some garbage sample rows may be included in the last iMCU
+ * row at the bottom of the image.
+ *
+ * Depending on the vertical scaling algorithm used, the upsampler may need
+ * access to the sample row(s) above and below its current input row group.
+ * The upsampler is required to set need_context_rows TRUE at global selection
+ * time if so.  When need_context_rows is FALSE, this controller can simply
+ * obtain one iMCU row at a time from the coefficient controller and dole it
+ * out as row groups to the postprocessor.
+ *
+ * When need_context_rows is TRUE, this controller guarantees that the buffer
+ * passed to postprocessing contains at least one row group's worth of samples
+ * above and below the row group(s) being processed.  Note that the context
+ * rows "above" the first passed row group appear at negative row offsets in
+ * the passed buffer.  At the top and bottom of the image, the required
+ * context rows are manufactured by duplicating the first or last real sample
+ * row; this avoids having special cases in the upsampling inner loops.
+ *
+ * The amount of context is fixed at one row group just because that's a
+ * convenient number for this controller to work with.  The existing
+ * upsamplers really only need one sample row of context.  An upsampler
+ * supporting arbitrary output rescaling might wish for more than one row
+ * group of context when shrinking the image; tough, we don't handle that.
+ * (This is justified by the assumption that downsizing will be handled mostly
+ * by adjusting the codec_data_unit values, so that the actual scale factor at
+ * the upsample step needn't be much less than one.)
+ *
+ * To provide the desired context, we have to retain the last two row groups
+ * of one iMCU row while reading in the next iMCU row.  (The last row group
+ * can't be processed until we have another row group for its below-context,
+ * and so we have to save the next-to-last group too for its above-context.)
+ * We could do this most simply by copying data around in our buffer, but
+ * that'd be very slow.  We can avoid copying any data by creating a rather
+ * strange pointer structure.  Here's how it works.  We allocate a workspace
+ * consisting of M+2 row groups (where M = min_codec_data_unit is the number
+ * of row groups per iMCU row).  We create two sets of redundant pointers to
+ * the workspace.  Labeling the physical row groups 0 to M+1, the synthesized
+ * pointer lists look like this:
+ *                   M+1                          M-1
+ * master pointer --> 0         master pointer --> 0
+ *                    1                            1
+ *                   ...                          ...
+ *                   M-3                          M-3
+ *                   M-2                           M
+ *                   M-1                          M+1
+ *                    M                           M-2
+ *                   M+1                          M-1
+ *                    0                            0
+ * We read alternate iMCU rows using each master pointer; thus the last two
+ * row groups of the previous iMCU row remain un-overwritten in the workspace.
+ * The pointer lists are set up so that the required context rows appear to
+ * be adjacent to the proper places when we pass the pointer lists to the
+ * upsampler.
+ *
+ * The above pictures describe the normal state of the pointer lists.
+ * At top and bottom of the image, we diddle the pointer lists to duplicate
+ * the first or last sample row as necessary (this is cheaper than copying
+ * sample rows around).
+ *
+ * This scheme breaks down if M < 2, ie, min_codec_data_unit is 1.  In that
+ * situation each iMCU row provides only one row group so the buffering logic
+ * must be different (eg, we must read two iMCU rows before we can emit the
+ * first row group).  For now, we simply do not support providing context
+ * rows when min_codec_data_unit is 1.  That combination seems unlikely to
+ * be worth providing --- if someone wants a 1/8th-size preview, they probably
+ * want it quick and dirty, so a context-free upsampler is sufficient.
+ */
+
+
+/* Private buffer controller object */
+
+typedef struct {
+  struct jpeg_d_main_controller pub; /* public fields */
+
+  /* Pointer to allocated workspace (M or M+2 row groups). */
+  JSAMPARRAY buffer[MAX_COMPONENTS];
+
+  boolean buffer_full;    /* Have we gotten an iMCU row from decoder? */
+  JDIMENSION rowgroup_ctr;  /* counts row groups output to postprocessor */
+
+  /* Remaining fields are only used in the context case. */
+
+  /* These are the master pointers to the funny-order pointer lists. */
+  JSAMPIMAGE xbuffer[2];  /* pointers to weird pointer lists */
+
+  int whichptr;      /* indicates which pointer set is now in use */
+  int context_state;    /* process_data state machine status */
+  JDIMENSION rowgroups_avail;  /* row groups available to postprocessor */
+  JDIMENSION iMCU_row_ctr;  /* counts iMCU rows to detect image top/bot */
+} my_main_controller;
+
+typedef my_main_controller * my_main_ptr;
+
+/* context_state values: */
+#define CTX_PREPARE_FOR_IMCU  0  /* need to prepare for MCU row */
+#define CTX_PROCESS_IMCU  1  /* feeding iMCU to postprocessor */
+#define CTX_POSTPONED_ROW  2  /* feeding postponed row group */
+
+
+/* Forward declarations */
+METHODDEF(void) process_data_simple_main
+  JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+       JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+METHODDEF(void) process_data_context_main
+  JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+       JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+#ifdef QUANT_2PASS_SUPPORTED
+METHODDEF(void) process_data_crank_post
+  JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+       JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+#endif
+
+
+LOCAL(void)
+alloc_funny_pointers (j_decompress_ptr cinfo)
+/* Allocate space for the funny pointer lists.
+ * This is done only once, not once per pass.
+ */
+{
+  my_main_ptr mainPtr = (my_main_ptr) cinfo->main;
+  int ci, rgroup;
+  int M = cinfo->min_codec_data_unit;
+  jpeg_component_info *compptr;
+  JSAMPARRAY xbuf;
+
+  /* Get top-level space for component array pointers.
+   * We alloc both arrays with one call to save a few cycles.
+   */
+  mainPtr->xbuffer[0] = (JSAMPIMAGE)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
+  mainPtr->xbuffer[1] = mainPtr->xbuffer[0] + cinfo->num_components;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
+      cinfo->min_codec_data_unit; /* height of a row group of component */
+    /* Get space for pointer lists --- M+4 row groups in each list.
+     * We alloc both pointer lists with one call to save a few cycles.
+     */
+    xbuf = (JSAMPARRAY)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
+    xbuf += rgroup;    /* want one row group at negative offsets */
+    mainPtr->xbuffer[0][ci] = xbuf;
+    xbuf += rgroup * (M + 4);
+    mainPtr->xbuffer[1][ci] = xbuf;
+  }
+}
+
+
+LOCAL(void)
+make_funny_pointers (j_decompress_ptr cinfo)
+/* Create the funny pointer lists discussed in the comments above.
+ * The actual workspace is already allocated (in mainPtr->buffer),
+ * and the space for the pointer lists is allocated too.
+ * This routine just fills in the curiously ordered lists.
+ * This will be repeated at the beginning of each pass.
+ */
+{
+  my_main_ptr mainPtr = (my_main_ptr) cinfo->main;
+  int ci, i, rgroup;
+  int M = cinfo->min_codec_data_unit;
+  jpeg_component_info *compptr;
+  JSAMPARRAY buf, xbuf0, xbuf1;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
+      cinfo->min_codec_data_unit; /* height of a row group of component */
+    xbuf0 = mainPtr->xbuffer[0][ci];
+    xbuf1 = mainPtr->xbuffer[1][ci];
+    /* First copy the workspace pointers as-is */
+    buf = mainPtr->buffer[ci];
+    for (i = 0; i < rgroup * (M + 2); i++) {
+      xbuf0[i] = xbuf1[i] = buf[i];
+    }
+    /* In the second list, put the last four row groups in swapped order */
+    for (i = 0; i < rgroup * 2; i++) {
+      xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
+      xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
+    }
+    /* The wraparound pointers at top and bottom will be filled later
+     * (see set_wraparound_pointers, below).  Initially we want the "above"
+     * pointers to duplicate the first actual data line.  This only needs
+     * to happen in xbuffer[0].
+     */
+    for (i = 0; i < rgroup; i++) {
+      xbuf0[i - rgroup] = xbuf0[0];
+    }
+  }
+}
+
+
+LOCAL(void)
+set_wraparound_pointers (j_decompress_ptr cinfo)
+/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
+ * This changes the pointer list state from top-of-image to the normal state.
+ */
+{
+  my_main_ptr mainPtr = (my_main_ptr) cinfo->main;
+  int ci, i, rgroup;
+  int M = cinfo->min_codec_data_unit;
+  jpeg_component_info *compptr;
+  JSAMPARRAY xbuf0, xbuf1;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
+      cinfo->min_codec_data_unit; /* height of a row group of component */
+    xbuf0 = mainPtr->xbuffer[0][ci];
+    xbuf1 = mainPtr->xbuffer[1][ci];
+    for (i = 0; i < rgroup; i++) {
+      xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
+      xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
+      xbuf0[rgroup*(M+2) + i] = xbuf0[i];
+      xbuf1[rgroup*(M+2) + i] = xbuf1[i];
+    }
+  }
+}
+
+
+LOCAL(void)
+set_bottom_pointers (j_decompress_ptr cinfo)
+/* Change the pointer lists to duplicate the last sample row at the bottom
+ * of the image.  whichptr indicates which xbuffer holds the final iMCU row.
+ * Also sets rowgroups_avail to indicate number of nondummy row groups in row.
+ */
+{
+  my_main_ptr mainPtr = (my_main_ptr) cinfo->main;
+  int ci, i, rgroup, iMCUheight, rows_left;
+  jpeg_component_info *compptr;
+  JSAMPARRAY xbuf;
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Count sample rows in one iMCU row and in one row group */
+    iMCUheight = compptr->v_samp_factor * compptr->codec_data_unit;
+    rgroup = iMCUheight / cinfo->min_codec_data_unit;
+    /* Count nondummy sample rows remaining for this component */
+    rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
+    if (rows_left == 0) rows_left = iMCUheight;
+    /* Count nondummy row groups.  Should get same answer for each component,
+     * so we need only do it once.
+     */
+    if (ci == 0) {
+      mainPtr->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
+    }
+    /* Duplicate the last real sample row rgroup*2 times; this pads out the
+     * last partial rowgroup and ensures at least one full rowgroup of context.
+     */
+    xbuf = mainPtr->xbuffer[mainPtr->whichptr][ci];
+    for (i = 0; i < rgroup * 2; i++) {
+      xbuf[rows_left + i] = xbuf[rows_left-1];
+    }
+  }
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+  my_main_ptr mainPtr = (my_main_ptr) cinfo->main;
+
+  switch (pass_mode) {
+  case JBUF_PASS_THRU:
+    if (cinfo->upsample->need_context_rows) {
+      mainPtr->pub.process_data = process_data_context_main;
+      make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
+      mainPtr->whichptr = 0;  /* Read first iMCU row into xbuffer[0] */
+      mainPtr->context_state = CTX_PREPARE_FOR_IMCU;
+      mainPtr->iMCU_row_ctr = 0;
+    } else {
+      /* Simple case with no context needed */
+      mainPtr->pub.process_data = process_data_simple_main;
+    }
+    mainPtr->buffer_full = FALSE;  /* Mark buffer empty */
+    mainPtr->rowgroup_ctr = 0;
+    break;
+#ifdef QUANT_2PASS_SUPPORTED
+  case JBUF_CRANK_DEST:
+    /* For last pass of 2-pass quantization, just crank the postprocessor */
+    mainPtr->pub.process_data = process_data_crank_post;
+    break;
+#endif
+  default:
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    break;
+  }
+}
+
+
+/*
+ * Process some data.
+ * This handles the simple case where no context is required.
+ */
+
+METHODDEF(void)
+process_data_simple_main (j_decompress_ptr cinfo,
+        JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+        JDIMENSION out_rows_avail)
+{
+  my_main_ptr mainPtr = (my_main_ptr) cinfo->main;
+  JDIMENSION rowgroups_avail;
+
+  /* Read input data if we haven't filled the main buffer yet */
+  if (! mainPtr->buffer_full) {
+    if (! (*cinfo->codec->decompress_data) (cinfo, mainPtr->buffer))
+      return;      /* suspension forced, can do nothing more */
+    mainPtr->buffer_full = TRUE;  /* OK, we have an iMCU row to work with */
+  }
+
+  /* There are always min_codec_data_unit row groups in an iMCU row. */
+  rowgroups_avail = (JDIMENSION) cinfo->min_codec_data_unit;
+  /* Note: at the bottom of the image, we may pass extra garbage row groups
+   * to the postprocessor.  The postprocessor has to check for bottom
+   * of image anyway (at row resolution), so no point in us doing it too.
+   */
+
+  /* Feed the postprocessor */
+  (*cinfo->post->post_process_data) (cinfo, mainPtr->buffer,
+             &mainPtr->rowgroup_ctr, rowgroups_avail,
+             output_buf, out_row_ctr, out_rows_avail);
+
+  /* Has postprocessor consumed all the data yet? If so, mark buffer empty */
+  if (mainPtr->rowgroup_ctr >= rowgroups_avail) {
+    mainPtr->buffer_full = FALSE;
+    mainPtr->rowgroup_ctr = 0;
+  }
+}
+
+
+/*
+ * Process some data.
+ * This handles the case where context rows must be provided.
+ */
+
+METHODDEF(void)
+process_data_context_main (j_decompress_ptr cinfo,
+         JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+         JDIMENSION out_rows_avail)
+{
+  my_main_ptr mainPtr = (my_main_ptr) cinfo->main;
+
+  /* Read input data if we haven't filled the main buffer yet */
+  if (! mainPtr->buffer_full) {
+    if (! (*cinfo->codec->decompress_data) (cinfo,
+             mainPtr->xbuffer[mainPtr->whichptr]))
+      return;      /* suspension forced, can do nothing more */
+    mainPtr->buffer_full = TRUE;  /* OK, we have an iMCU row to work with */
+    mainPtr->iMCU_row_ctr++;  /* count rows received */
+  }
+
+  /* Postprocessor typically will not swallow all the input data it is handed
+   * in one call (due to filling the output buffer first).  Must be prepared
+   * to exit and restart.  This switch lets us keep track of how far we got.
+   * Note that each case falls through to the next on successful completion.
+   */
+  switch (mainPtr->context_state) {
+  case CTX_POSTPONED_ROW:
+    /* Call postprocessor using previously set pointers for postponed row */
+    (*cinfo->post->post_process_data) (cinfo, mainPtr->xbuffer[mainPtr->whichptr],
+      &mainPtr->rowgroup_ctr, mainPtr->rowgroups_avail,
+      output_buf, out_row_ctr, out_rows_avail);
+    if (mainPtr->rowgroup_ctr < mainPtr->rowgroups_avail)
+      return;      /* Need to suspend */
+    mainPtr->context_state = CTX_PREPARE_FOR_IMCU;
+    if (*out_row_ctr >= out_rows_avail)
+      return;      /* Postprocessor exactly filled output buf */
+    /*FALLTHROUGH*/
+  case CTX_PREPARE_FOR_IMCU:
+    /* Prepare to process first M-1 row groups of this iMCU row */
+    mainPtr->rowgroup_ctr = 0;
+    mainPtr->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit - 1);
+    /* Check for bottom of image: if so, tweak pointers to "duplicate"
+     * the last sample row, and adjust rowgroups_avail to ignore padding rows.
+     */
+    if (mainPtr->iMCU_row_ctr == cinfo->total_iMCU_rows)
+      set_bottom_pointers(cinfo);
+    mainPtr->context_state = CTX_PROCESS_IMCU;
+    /*FALLTHROUGH*/
+  case CTX_PROCESS_IMCU:
+    /* Call postprocessor using previously set pointers */
+    (*cinfo->post->post_process_data) (cinfo, mainPtr->xbuffer[mainPtr->whichptr],
+      &mainPtr->rowgroup_ctr, mainPtr->rowgroups_avail,
+      output_buf, out_row_ctr, out_rows_avail);
+    if (mainPtr->rowgroup_ctr < mainPtr->rowgroups_avail)
+      return;      /* Need to suspend */
+    /* After the first iMCU, change wraparound pointers to normal state */
+    if (mainPtr->iMCU_row_ctr == 1)
+      set_wraparound_pointers(cinfo);
+    /* Prepare to load new iMCU row using other xbuffer list */
+    mainPtr->whichptr ^= 1;  /* 0=>1 or 1=>0 */
+    mainPtr->buffer_full = FALSE;
+    /* Still need to process last row group of this iMCU row, */
+    /* which is saved at index M+1 of the other xbuffer */
+    mainPtr->rowgroup_ctr = (JDIMENSION) (cinfo->min_codec_data_unit + 1);
+    mainPtr->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit + 2);
+    mainPtr->context_state = CTX_POSTPONED_ROW;
+  }
+}
+
+
+/*
+ * Process some data.
+ * Final pass of two-pass quantization: just call the postprocessor.
+ * Source data will be the postprocessor controller's internal buffer.
+ */
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+METHODDEF(void)
+process_data_crank_post (j_decompress_ptr cinfo,
+       JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+       JDIMENSION out_rows_avail)
+{
+  (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
+             (JDIMENSION *) NULL, (JDIMENSION) 0,
+             output_buf, out_row_ctr, out_rows_avail);
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+
+
+/*
+ * Initialize main buffer controller.
+ */
+
+GLOBAL(void)
+jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+  my_main_ptr mainPtr;
+  int ci, rgroup, ngroups;
+  jpeg_component_info *compptr;
+
+  mainPtr = (my_main_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_main_controller));
+  cinfo->main = (struct jpeg_d_main_controller *) mainPtr;
+  mainPtr->pub.start_pass = start_pass_main;
+
+  if (need_full_buffer)    /* shouldn't happen */
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+  /* Allocate the workspace.
+   * ngroups is the number of row groups we need.
+   */
+  if (cinfo->upsample->need_context_rows) {
+    if (cinfo->min_codec_data_unit < 2) /* unsupported, see comments above */
+      ERREXIT(cinfo, JERR_NOTIMPL);
+    alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
+    ngroups = cinfo->min_codec_data_unit + 2;
+  } else {
+    ngroups = cinfo->min_codec_data_unit;
+  }
+
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
+      cinfo->min_codec_data_unit; /* height of a row group of component */
+    mainPtr->buffer[ci] = (*cinfo->mem->alloc_sarray)
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       compptr->width_in_data_units * compptr->codec_data_unit,
+       (JDIMENSION) (rgroup * ngroups));
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdmarker.c b/Utilities/ITK/Utilities/itkjpeg/jdmarker.c
new file mode 100644
index 0000000000000000000000000000000000000000..e280621b295bc88d09d159c4ec75a665073c2920
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdmarker.c
@@ -0,0 +1,1370 @@
+/*
+ * jdmarker.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to decode JPEG datastream markers.
+ * Most of the complexity arises from our desire to support input
+ * suspension: if not all of the data for a marker is available,
+ * we must exit back to the application.  On resumption, we reprocess
+ * the marker.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+typedef enum {      /* JPEG marker codes */
+  M_SOF0  = 0xc0,
+  M_SOF1  = 0xc1,
+  M_SOF2  = 0xc2,
+  M_SOF3  = 0xc3,
+  
+  M_SOF5  = 0xc5,
+  M_SOF6  = 0xc6,
+  M_SOF7  = 0xc7,
+  
+  M_JPG   = 0xc8,
+  M_SOF9  = 0xc9,
+  M_SOF10 = 0xca,
+  M_SOF11 = 0xcb,
+  
+  M_SOF13 = 0xcd,
+  M_SOF14 = 0xce,
+  M_SOF15 = 0xcf,
+  
+  M_DHT   = 0xc4,
+  
+  M_DAC   = 0xcc,
+  
+  M_RST0  = 0xd0,
+  M_RST1  = 0xd1,
+  M_RST2  = 0xd2,
+  M_RST3  = 0xd3,
+  M_RST4  = 0xd4,
+  M_RST5  = 0xd5,
+  M_RST6  = 0xd6,
+  M_RST7  = 0xd7,
+  
+  M_SOI   = 0xd8,
+  M_EOI   = 0xd9,
+  M_SOS   = 0xda,
+  M_DQT   = 0xdb,
+  M_DNL   = 0xdc,
+  M_DRI   = 0xdd,
+  M_DHP   = 0xde,
+  M_EXP   = 0xdf,
+  
+  M_APP0  = 0xe0,
+  M_APP1  = 0xe1,
+  M_APP2  = 0xe2,
+  M_APP3  = 0xe3,
+  M_APP4  = 0xe4,
+  M_APP5  = 0xe5,
+  M_APP6  = 0xe6,
+  M_APP7  = 0xe7,
+  M_APP8  = 0xe8,
+  M_APP9  = 0xe9,
+  M_APP10 = 0xea,
+  M_APP11 = 0xeb,
+  M_APP12 = 0xec,
+  M_APP13 = 0xed,
+  M_APP14 = 0xee,
+  M_APP15 = 0xef,
+  
+  M_JPG0  = 0xf0,
+  M_JPG13 = 0xfd,
+  M_COM   = 0xfe,
+  
+  M_TEM   = 0x01,
+  
+  M_ERROR = 0x100
+} JPEG_MARKER;
+
+
+/* Private state */
+
+typedef struct {
+  struct jpeg_marker_reader pub; /* public fields */
+
+  /* Application-overridable marker processing methods */
+  jpeg_marker_parser_method process_COM;
+  jpeg_marker_parser_method process_APPn[16];
+
+  /* Limit on marker data length to save for each marker type */
+  unsigned int length_limit_COM;
+  unsigned int length_limit_APPn[16];
+
+  /* Status of COM/APPn marker saving */
+  jpeg_saved_marker_ptr cur_marker;  /* NULL if not processing a marker */
+  unsigned int bytes_read;    /* data bytes read so far in marker */
+  /* Note: cur_marker is not linked into marker_list until it's all read. */
+} my_marker_reader;
+
+typedef my_marker_reader * my_marker_ptr;
+
+
+/*
+ * Macros for fetching data from the data source module.
+ *
+ * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect
+ * the current restart point; we update them only when we have reached a
+ * suitable place to restart if a suspension occurs.
+ */
+
+/* Declare and initialize local copies of input pointer/count */
+#define INPUT_VARS(cinfo)  \
+  struct jpeg_source_mgr * datasrc = (cinfo)->src;  \
+  const JOCTET * next_input_byte = datasrc->next_input_byte;  \
+  size_t bytes_in_buffer = datasrc->bytes_in_buffer
+
+/* Unload the local copies --- do this only at a restart boundary */
+#define INPUT_SYNC(cinfo)  \
+  ( datasrc->next_input_byte = next_input_byte,  \
+    datasrc->bytes_in_buffer = bytes_in_buffer )
+
+/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */
+#define INPUT_RELOAD(cinfo)  \
+  ( next_input_byte = datasrc->next_input_byte,  \
+    bytes_in_buffer = datasrc->bytes_in_buffer )
+
+/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
+ * Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
+ * but we must reload the local copies after a successful fill.
+ */
+#define MAKE_BYTE_AVAIL(cinfo,action)  \
+  if (bytes_in_buffer == 0) {  \
+    if (! (*datasrc->fill_input_buffer) (cinfo))  \
+      { action; }  \
+    INPUT_RELOAD(cinfo);  \
+  }
+
+/* Read a byte into variable V.
+ * If must suspend, take the specified action (typically "return FALSE").
+ */
+#define INPUT_BYTE(cinfo,V,action)  \
+  MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
+      bytes_in_buffer--; \
+      V = GETJOCTET(*next_input_byte++); )
+
+/* As above, but read two bytes interpreted as an unsigned 16-bit integer.
+ * V should be declared unsigned int or perhaps INT32.
+ */
+#define INPUT_2BYTES(cinfo,V,action)  \
+  MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
+      bytes_in_buffer--; \
+      V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
+      MAKE_BYTE_AVAIL(cinfo,action); \
+      bytes_in_buffer--; \
+      V += GETJOCTET(*next_input_byte++); )
+
+
+/*
+ * Routines to process JPEG markers.
+ *
+ * Entry condition: JPEG marker itself has been read and its code saved
+ *   in cinfo->unread_marker; input restart point is just after the marker.
+ *
+ * Exit: if return TRUE, have read and processed any parameters, and have
+ *   updated the restart point to point after the parameters.
+ *   If return FALSE, was forced to suspend before reaching end of
+ *   marker parameters; restart point has not been moved.  Same routine
+ *   will be called again after application supplies more input data.
+ *
+ * This approach to suspension assumes that all of a marker's parameters
+ * can fit into a single input bufferload.  This should hold for "normal"
+ * markers.  Some COM/APPn markers might have large parameter segments
+ * that might not fit.  If we are simply dropping such a marker, we use
+ * skip_input_data to get past it, and thereby put the problem on the
+ * source manager's shoulders.  If we are saving the marker's contents
+ * into memory, we use a slightly different convention: when forced to
+ * suspend, the marker processor updates the restart point to the end of
+ * what it's consumed (ie, the end of the buffer) before returning FALSE.
+ * On resumption, cinfo->unread_marker still contains the marker code,
+ * but the data source will point to the next chunk of marker data.
+ * The marker processor must retain internal state to deal with this.
+ *
+ * Note that we don't bother to avoid duplicate trace messages if a
+ * suspension occurs within marker parameters.  Other side effects
+ * require more care.
+ */
+
+
+LOCAL(boolean)
+get_soi (j_decompress_ptr cinfo)
+/* Process an SOI marker */
+{
+  int i;
+  
+  TRACEMS(cinfo, 1, JTRC_SOI);
+
+  if (cinfo->marker->saw_SOI)
+    ERREXIT(cinfo, JERR_SOI_DUPLICATE);
+
+  /* Reset all parameters that are defined to be reset by SOI */
+
+  for (i = 0; i < NUM_ARITH_TBLS; i++) {
+    cinfo->arith_dc_L[i] = 0;
+    cinfo->arith_dc_U[i] = 1;
+    cinfo->arith_ac_K[i] = 5;
+  }
+  cinfo->restart_interval = 0;
+
+  /* Set initial assumptions for colorspace etc */
+
+  cinfo->jpeg_color_space = JCS_UNKNOWN;
+  cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */
+
+  cinfo->saw_JFIF_marker = FALSE;
+  cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */
+  cinfo->JFIF_minor_version = 1;
+  cinfo->density_unit = 0;
+  cinfo->X_density = 1;
+  cinfo->Y_density = 1;
+  cinfo->saw_Adobe_marker = FALSE;
+  cinfo->Adobe_transform = 0;
+
+  cinfo->marker->saw_SOI = TRUE;
+
+  return TRUE;
+}
+
+
+LOCAL(boolean)
+get_sof (j_decompress_ptr cinfo, J_CODEC_PROCESS process, boolean is_arith,
+   int data_unit)
+/* Process a SOFn marker */
+{
+  INT32 length;
+  int c, ci;
+  jpeg_component_info * compptr;
+  INPUT_VARS(cinfo);
+
+  cinfo->data_unit = data_unit;
+  cinfo->process = process;
+  cinfo->arith_code = is_arith;
+
+  INPUT_2BYTES(cinfo, length, return FALSE);
+
+  INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE);
+  INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE);
+  INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE);
+  INPUT_BYTE(cinfo, cinfo->num_components, return FALSE);
+
+  length -= 8;
+
+  TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker,
+     (int) cinfo->image_width, (int) cinfo->image_height,
+     cinfo->num_components);
+
+  if (cinfo->marker->saw_SOF)
+    ERREXIT(cinfo, JERR_SOF_DUPLICATE);
+
+  /* We don't support files in which the image height is initially specified */
+  /* as 0 and is later redefined by DNL.  As long as we have to check that,  */
+  /* might as well have a general sanity check. */
+  if (cinfo->image_height <= 0 || cinfo->image_width <= 0
+      || cinfo->num_components <= 0)
+    ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
+  if (length != (cinfo->num_components * 3))
+    ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+  if (cinfo->comp_info == NULL)  /* do only once, even if suspend */
+    cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small)
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       cinfo->num_components * SIZEOF(jpeg_component_info));
+  
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    compptr->component_index = ci;
+    INPUT_BYTE(cinfo, compptr->component_id, return FALSE);
+    INPUT_BYTE(cinfo, c, return FALSE);
+    compptr->h_samp_factor = (c >> 4) & 15;
+    compptr->v_samp_factor = (c     ) & 15;
+    INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE);
+
+    TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT,
+       compptr->component_id, compptr->h_samp_factor,
+       compptr->v_samp_factor, compptr->quant_tbl_no);
+  }
+
+  cinfo->marker->saw_SOF = TRUE;
+
+  INPUT_SYNC(cinfo);
+  return TRUE;
+}
+
+
+LOCAL(boolean)
+get_sos (j_decompress_ptr cinfo)
+/* Process a SOS marker */
+{
+  INT32 length;
+  int i, ci, n, c, cc;
+  jpeg_component_info * compptr;
+  INPUT_VARS(cinfo);
+
+  if (! cinfo->marker->saw_SOF)
+    ERREXIT(cinfo, JERR_SOS_NO_SOF);
+
+  INPUT_2BYTES(cinfo, length, return FALSE);
+
+  INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */
+
+  TRACEMS1(cinfo, 1, JTRC_SOS, n);
+
+  if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN)
+    ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+  cinfo->comps_in_scan = n;
+
+  /* Collect the component-spec parameters */
+
+  for (i = 0; i < n; i++) {
+    INPUT_BYTE(cinfo, cc, return FALSE);
+    INPUT_BYTE(cinfo, c, return FALSE);
+    
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      if (cc == compptr->component_id)
+  goto id_found;
+    }
+
+    ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
+
+  id_found:
+
+    cinfo->cur_comp_info[i] = compptr;
+    compptr->dc_tbl_no = (c >> 4) & 15;
+    compptr->ac_tbl_no = (c     ) & 15;
+    
+    TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,
+       compptr->dc_tbl_no, compptr->ac_tbl_no);
+  }
+
+  /* Collect the additional scan parameters Ss, Se, Ah/Al. */
+  INPUT_BYTE(cinfo, c, return FALSE);
+  cinfo->Ss = c;
+  INPUT_BYTE(cinfo, c, return FALSE);
+  cinfo->Se = c;
+  INPUT_BYTE(cinfo, c, return FALSE);
+  cinfo->Ah = (c >> 4) & 15;
+  cinfo->Al = (c     ) & 15;
+
+  TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se,
+     cinfo->Ah, cinfo->Al);
+
+  /* Prepare to scan data & restart markers */
+  cinfo->marker->next_restart_num = 0;
+
+  /* Count another SOS marker */
+  cinfo->input_scan_number++;
+
+  INPUT_SYNC(cinfo);
+  return TRUE;
+}
+
+
+#ifdef D_ARITH_CODING_SUPPORTED
+
+LOCAL(boolean)
+get_dac (j_decompress_ptr cinfo)
+/* Process a DAC marker */
+{
+  INT32 length;
+  int index, val;
+  INPUT_VARS(cinfo);
+
+  INPUT_2BYTES(cinfo, length, return FALSE);
+  length -= 2;
+  
+  while (length > 0) {
+    INPUT_BYTE(cinfo, index, return FALSE);
+    INPUT_BYTE(cinfo, val, return FALSE);
+
+    length -= 2;
+
+    TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
+
+    if (index < 0 || index >= (2*NUM_ARITH_TBLS))
+      ERREXIT1(cinfo, JERR_DAC_INDEX, index);
+
+    if (index >= NUM_ARITH_TBLS) { /* define AC table */
+      cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
+    } else {      /* define DC table */
+      cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
+      cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
+      if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
+  ERREXIT1(cinfo, JERR_DAC_VALUE, val);
+    }
+  }
+
+  if (length != 0)
+    ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+  INPUT_SYNC(cinfo);
+  return TRUE;
+}
+
+#else /* ! D_ARITH_CODING_SUPPORTED */
+
+#define get_dac(cinfo)  skip_variable(cinfo)
+
+#endif /* D_ARITH_CODING_SUPPORTED */
+
+
+LOCAL(boolean)
+get_dht (j_decompress_ptr cinfo)
+/* Process a DHT marker */
+{
+  INT32 length;
+  UINT8 bits[17];
+  UINT8 huffval[256];
+  int i, index, count;
+  JHUFF_TBL **htblptr;
+  INPUT_VARS(cinfo);
+
+  INPUT_2BYTES(cinfo, length, return FALSE);
+  length -= 2;
+  
+  while (length > 16) {
+    INPUT_BYTE(cinfo, index, return FALSE);
+
+    TRACEMS1(cinfo, 1, JTRC_DHT, index);
+      
+    bits[0] = 0;
+    count = 0;
+    for (i = 1; i <= 16; i++) {
+      INPUT_BYTE(cinfo, bits[i], return FALSE);
+      count += bits[i];
+    }
+
+    length -= 1 + 16;
+
+    TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
+       bits[1], bits[2], bits[3], bits[4],
+       bits[5], bits[6], bits[7], bits[8]);
+    TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
+       bits[9], bits[10], bits[11], bits[12],
+       bits[13], bits[14], bits[15], bits[16]);
+
+    /* Here we just do minimal validation of the counts to avoid walking
+     * off the end of our table space.  jdhuff.c will check more carefully.
+     */
+    if (count > 256 || ((INT32) count) > length)
+      ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+
+    for (i = 0; i < count; i++)
+      INPUT_BYTE(cinfo, huffval[i], return FALSE);
+
+    length -= count;
+
+    if (index & 0x10) {    /* AC table definition */
+      index -= 0x10;
+      htblptr = &cinfo->ac_huff_tbl_ptrs[index];
+    } else {      /* DC table definition */
+      htblptr = &cinfo->dc_huff_tbl_ptrs[index];
+    }
+
+    if (index < 0 || index >= NUM_HUFF_TBLS)
+      ERREXIT1(cinfo, JERR_DHT_INDEX, index);
+
+    if (*htblptr == NULL)
+      *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+  
+    MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
+    MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval));
+  }
+
+  if (length != 0)
+    ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+  INPUT_SYNC(cinfo);
+  return TRUE;
+}
+
+
+LOCAL(boolean)
+get_dqt (j_decompress_ptr cinfo)
+/* Process a DQT marker */
+{
+  INT32 length;
+  int n, i, prec;
+  unsigned int tmp;
+  JQUANT_TBL *quant_ptr;
+  INPUT_VARS(cinfo);
+
+  INPUT_2BYTES(cinfo, length, return FALSE);
+  length -= 2;
+
+  while (length > 0) {
+    INPUT_BYTE(cinfo, n, return FALSE);
+    prec = n >> 4;
+    n &= 0x0F;
+
+    TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);
+
+    if (n >= NUM_QUANT_TBLS)
+      ERREXIT1(cinfo, JERR_DQT_INDEX, n);
+      
+    if (cinfo->quant_tbl_ptrs[n] == NULL)
+      cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+    quant_ptr = cinfo->quant_tbl_ptrs[n];
+
+    for (i = 0; i < DCTSIZE2; i++) {
+      if (prec)
+  INPUT_2BYTES(cinfo, tmp, return FALSE);
+      else
+  INPUT_BYTE(cinfo, tmp, return FALSE);
+      /* We convert the zigzag-order table to natural array order. */
+      quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp;
+    }
+
+    if (cinfo->err->trace_level >= 2) {
+      for (i = 0; i < DCTSIZE2; i += 8) {
+  TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
+     quant_ptr->quantval[i],   quant_ptr->quantval[i+1],
+     quant_ptr->quantval[i+2], quant_ptr->quantval[i+3],
+     quant_ptr->quantval[i+4], quant_ptr->quantval[i+5],
+     quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]);
+      }
+    }
+
+    length -= DCTSIZE2+1;
+    if (prec) length -= DCTSIZE2;
+  }
+
+  if (length != 0)
+    ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+  INPUT_SYNC(cinfo);
+  return TRUE;
+}
+
+
+LOCAL(boolean)
+get_dri (j_decompress_ptr cinfo)
+/* Process a DRI marker */
+{
+  INT32 length;
+  unsigned int tmp;
+  INPUT_VARS(cinfo);
+
+  INPUT_2BYTES(cinfo, length, return FALSE);
+  
+  if (length != 4)
+    ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+  INPUT_2BYTES(cinfo, tmp, return FALSE);
+
+  TRACEMS1(cinfo, 1, JTRC_DRI, tmp);
+
+  cinfo->restart_interval = tmp;
+
+  INPUT_SYNC(cinfo);
+  return TRUE;
+}
+
+
+/*
+ * Routines for processing APPn and COM markers.
+ * These are either saved in memory or discarded, per application request.
+ * APP0 and APP14 are specially checked to see if they are
+ * JFIF and Adobe markers, respectively.
+ */
+
+#define APP0_DATA_LEN  14  /* Length of interesting data in APP0 */
+#define APP14_DATA_LEN  12  /* Length of interesting data in APP14 */
+#define APPN_DATA_LEN  14  /* Must be the largest of the above!! */
+
+
+LOCAL(void)
+examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data,
+        unsigned int datalen, INT32 remaining)
+/* Examine first few bytes from an APP0.
+ * Take appropriate action if it is a JFIF marker.
+ * datalen is # of bytes at data[], remaining is length of rest of marker data.
+ */
+{
+  INT32 totallen = (INT32) datalen + remaining;
+
+  if (datalen >= APP0_DATA_LEN &&
+      GETJOCTET(data[0]) == 0x4A &&
+      GETJOCTET(data[1]) == 0x46 &&
+      GETJOCTET(data[2]) == 0x49 &&
+      GETJOCTET(data[3]) == 0x46 &&
+      GETJOCTET(data[4]) == 0) {
+    /* Found JFIF APP0 marker: save info */
+    cinfo->saw_JFIF_marker = TRUE;
+    cinfo->JFIF_major_version = GETJOCTET(data[5]);
+    cinfo->JFIF_minor_version = GETJOCTET(data[6]);
+    cinfo->density_unit = GETJOCTET(data[7]);
+    cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]);
+    cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]);
+    /* Check version.
+     * Major version must be 1, anything else signals an incompatible change.
+     * (We used to treat this as an error, but now it's a nonfatal warning,
+     * because some bozo at Hijaak couldn't read the spec.)
+     * Minor version should be 0..2, but process anyway if newer.
+     */
+    if (cinfo->JFIF_major_version != 1)
+      WARNMS2(cinfo, JWRN_JFIF_MAJOR,
+        cinfo->JFIF_major_version, cinfo->JFIF_minor_version);
+    /* Generate trace messages */
+    TRACEMS5(cinfo, 1, JTRC_JFIF,
+       cinfo->JFIF_major_version, cinfo->JFIF_minor_version,
+       cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
+    /* Validate thumbnail dimensions and issue appropriate messages */
+    if (GETJOCTET(data[12]) | GETJOCTET(data[13]))
+      TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL,
+         GETJOCTET(data[12]), GETJOCTET(data[13]));
+    totallen -= APP0_DATA_LEN;
+    if (totallen !=
+  ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3))
+      TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen);
+  } else if (datalen >= 6 &&
+      GETJOCTET(data[0]) == 0x4A &&
+      GETJOCTET(data[1]) == 0x46 &&
+      GETJOCTET(data[2]) == 0x58 &&
+      GETJOCTET(data[3]) == 0x58 &&
+      GETJOCTET(data[4]) == 0) {
+    /* Found JFIF "JFXX" extension APP0 marker */
+    /* The library doesn't actually do anything with these,
+     * but we try to produce a helpful trace message.
+     */
+    switch (GETJOCTET(data[5])) {
+    case 0x10:
+      TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen);
+      break;
+    case 0x11:
+      TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen);
+      break;
+    case 0x13:
+      TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen);
+      break;
+    default:
+      TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION,
+         GETJOCTET(data[5]), (int) totallen);
+      break;
+    }
+  } else {
+    /* Start of APP0 does not match "JFIF" or "JFXX", or too short */
+    TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen);
+  }
+}
+
+
+LOCAL(void)
+examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data,
+         unsigned int datalen, INT32 remaining)
+/* Examine first few bytes from an APP14.
+ * Take appropriate action if it is an Adobe marker.
+ * datalen is # of bytes at data[], remaining is length of rest of marker data.
+ */
+{
+  unsigned int version, flags0, flags1, transform;
+
+  if (datalen >= APP14_DATA_LEN &&
+      GETJOCTET(data[0]) == 0x41 &&
+      GETJOCTET(data[1]) == 0x64 &&
+      GETJOCTET(data[2]) == 0x6F &&
+      GETJOCTET(data[3]) == 0x62 &&
+      GETJOCTET(data[4]) == 0x65) {
+    /* Found Adobe APP14 marker */
+    version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]);
+    flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]);
+    flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]);
+    transform = GETJOCTET(data[11]);
+    TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
+    cinfo->saw_Adobe_marker = TRUE;
+    cinfo->Adobe_transform = (UINT8) transform;
+  } else {
+    /* Start of APP14 does not match "Adobe", or too short */
+    TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
+  }
+}
+
+
+METHODDEF(boolean)
+get_interesting_appn (j_decompress_ptr cinfo)
+/* Process an APP0 or APP14 marker without saving it */
+{
+  INT32 length;
+  JOCTET b[APPN_DATA_LEN];
+  unsigned int i, numtoread;
+  INPUT_VARS(cinfo);
+
+  INPUT_2BYTES(cinfo, length, return FALSE);
+  length -= 2;
+
+  /* get the interesting part of the marker data */
+  if (length >= APPN_DATA_LEN)
+    numtoread = APPN_DATA_LEN;
+  else if (length > 0)
+    numtoread = (unsigned int) length;
+  else
+    numtoread = 0;
+  for (i = 0; i < numtoread; i++)
+    INPUT_BYTE(cinfo, b[i], return FALSE);
+  length -= numtoread;
+
+  /* process it */
+  switch (cinfo->unread_marker) {
+  case M_APP0:
+    examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length);
+    break;
+  case M_APP14:
+    examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length);
+    break;
+  default:
+    /* can't get here unless jpeg_save_markers chooses wrong processor */
+    ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
+    break;
+  }
+
+  /* skip any remaining data -- could be lots */
+  INPUT_SYNC(cinfo);
+  if (length > 0)
+    (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+  return TRUE;
+}
+
+
+#ifdef SAVE_MARKERS_SUPPORTED
+
+METHODDEF(boolean)
+save_marker (j_decompress_ptr cinfo)
+/* Save an APPn or COM marker into the marker list */
+{
+  my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+  jpeg_saved_marker_ptr cur_marker = marker->cur_marker;
+  unsigned int bytes_read, data_length;
+  JOCTET FAR * data;
+  INT32 length = 0;
+  INPUT_VARS(cinfo);
+
+  if (cur_marker == NULL) {
+    /* begin reading a marker */
+    INPUT_2BYTES(cinfo, length, return FALSE);
+    length -= 2;
+    if (length >= 0) {    /* watch out for bogus length word */
+      /* figure out how much we want to save */
+      unsigned int limit;
+      if (cinfo->unread_marker == (int) M_COM)
+  limit = marker->length_limit_COM;
+      else
+  limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0];
+      if ((unsigned int) length < limit)
+  limit = (unsigned int) length;
+      /* allocate and initialize the marker item */
+      cur_marker = (jpeg_saved_marker_ptr)
+  (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+            SIZEOF(struct jpeg_marker_struct) + limit);
+      cur_marker->next = NULL;
+      cur_marker->marker = (UINT8) cinfo->unread_marker;
+      cur_marker->original_length = (unsigned int) length;
+      cur_marker->data_length = limit;
+      /* data area is just beyond the jpeg_marker_struct */
+      data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1);
+      marker->cur_marker = cur_marker;
+      marker->bytes_read = 0;
+      bytes_read = 0;
+      data_length = limit;
+    } else {
+      /* deal with bogus length word */
+      bytes_read = data_length = 0;
+      data = NULL;
+    }
+  } else {
+    /* resume reading a marker */
+    bytes_read = marker->bytes_read;
+    data_length = cur_marker->data_length;
+    data = cur_marker->data + bytes_read;
+  }
+
+  while (bytes_read < data_length) {
+    INPUT_SYNC(cinfo);    /* move the restart point to here */
+    marker->bytes_read = bytes_read;
+    /* If there's not at least one byte in buffer, suspend */
+    MAKE_BYTE_AVAIL(cinfo, return FALSE);
+    /* Copy bytes with reasonable rapidity */
+    while (bytes_read < data_length && bytes_in_buffer > 0) {
+      *data++ = *next_input_byte++;
+      bytes_in_buffer--;
+      bytes_read++;
+    }
+  }
+
+  /* Done reading what we want to read */
+  if (cur_marker != NULL) {  /* will be NULL if bogus length word */
+    /* Add new marker to end of list */
+    if (cinfo->marker_list == NULL) {
+      cinfo->marker_list = cur_marker;
+    } else {
+      jpeg_saved_marker_ptr prev = cinfo->marker_list;
+      while (prev->next != NULL)
+  prev = prev->next;
+      prev->next = cur_marker;
+    }
+    /* Reset pointer & calc remaining data length */
+    data = cur_marker->data;
+    length = cur_marker->original_length - data_length;
+  }
+  /* Reset to initial state for next marker */
+  marker->cur_marker = NULL;
+
+  /* Process the marker if interesting; else just make a generic trace msg */
+  switch (cinfo->unread_marker) {
+  case M_APP0:
+    examine_app0(cinfo, data, data_length, length);
+    break;
+  case M_APP14:
+    examine_app14(cinfo, data, data_length, length);
+    break;
+  default:
+    TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker,
+       (int) (data_length + length));
+    break;
+  }
+
+  /* skip any remaining data -- could be lots */
+  INPUT_SYNC(cinfo);    /* do before skip_input_data */
+  if (length > 0)
+    (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+  return TRUE;
+}
+
+#endif /* SAVE_MARKERS_SUPPORTED */
+
+
+METHODDEF(boolean)
+skip_variable (j_decompress_ptr cinfo)
+/* Skip over an unknown or uninteresting variable-length marker */
+{
+  INT32 length;
+  INPUT_VARS(cinfo);
+
+  INPUT_2BYTES(cinfo, length, return FALSE);
+  length -= 2;
+  
+  TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length);
+
+  INPUT_SYNC(cinfo);    /* do before skip_input_data */
+  if (length > 0)
+    (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+  return TRUE;
+}
+
+
+/*
+ * Find the next JPEG marker, save it in cinfo->unread_marker.
+ * Returns FALSE if had to suspend before reaching a marker;
+ * in that case cinfo->unread_marker is unchanged.
+ *
+ * Note that the result might not be a valid marker code,
+ * but it will never be 0 or FF.
+ */
+
+LOCAL(boolean)
+next_marker (j_decompress_ptr cinfo)
+{
+  int c;
+  INPUT_VARS(cinfo);
+
+  for (;;) {
+    INPUT_BYTE(cinfo, c, return FALSE);
+    /* Skip any non-FF bytes.
+     * This may look a bit inefficient, but it will not occur in a valid file.
+     * We sync after each discarded byte so that a suspending data source
+     * can discard the byte from its buffer.
+     */
+    while (c != 0xFF) {
+      cinfo->marker->discarded_bytes++;
+      INPUT_SYNC(cinfo);
+      INPUT_BYTE(cinfo, c, return FALSE);
+    }
+    /* This loop swallows any duplicate FF bytes.  Extra FFs are legal as
+     * pad bytes, so don't count them in discarded_bytes.  We assume there
+     * will not be so many consecutive FF bytes as to overflow a suspending
+     * data source's input buffer.
+     */
+    do {
+      INPUT_BYTE(cinfo, c, return FALSE);
+    } while (c == 0xFF);
+    if (c != 0)
+      break;      /* found a valid marker, exit loop */
+    /* Reach here if we found a stuffed-zero data sequence (FF/00).
+     * Discard it and loop back to try again.
+     */
+    cinfo->marker->discarded_bytes += 2;
+    INPUT_SYNC(cinfo);
+  }
+
+  if (cinfo->marker->discarded_bytes != 0) {
+    WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c);
+    cinfo->marker->discarded_bytes = 0;
+  }
+
+  cinfo->unread_marker = c;
+
+  INPUT_SYNC(cinfo);
+  return TRUE;
+}
+
+
+LOCAL(boolean)
+first_marker (j_decompress_ptr cinfo)
+/* Like next_marker, but used to obtain the initial SOI marker. */
+/* For this marker, we do not allow preceding garbage or fill; otherwise,
+ * we might well scan an entire input file before realizing it ain't JPEG.
+ * If an application wants to process non-JFIF files, it must seek to the
+ * SOI before calling the JPEG library.
+ */
+{
+  int c, c2;
+  INPUT_VARS(cinfo);
+
+  INPUT_BYTE(cinfo, c, return FALSE);
+  INPUT_BYTE(cinfo, c2, return FALSE);
+  if (c != 0xFF || c2 != (int) M_SOI)
+    ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
+
+  cinfo->unread_marker = c2;
+
+  INPUT_SYNC(cinfo);
+  return TRUE;
+}
+
+
+/*
+ * Read markers until SOS or EOI.
+ *
+ * Returns same codes as are defined for jpeg_consume_input:
+ * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ */
+
+METHODDEF(int)
+read_markers (j_decompress_ptr cinfo)
+{
+  /* Outer loop repeats once for each marker. */
+  for (;;) {
+    /* Collect the marker proper, unless we already did. */
+    /* NB: first_marker() enforces the requirement that SOI appear first. */
+    if (cinfo->unread_marker == 0) {
+      if (! cinfo->marker->saw_SOI) {
+  if (! first_marker(cinfo))
+    return JPEG_SUSPENDED;
+      } else {
+  if (! next_marker(cinfo))
+    return JPEG_SUSPENDED;
+      }
+    }
+    /* At this point cinfo->unread_marker contains the marker code and the
+     * input point is just past the marker proper, but before any parameters.
+     * A suspension will cause us to return with this state still true.
+     */
+    switch (cinfo->unread_marker) {
+    case M_SOI:
+      if (! get_soi(cinfo))
+  return JPEG_SUSPENDED;
+      break;
+
+    case M_SOF0:    /* Baseline */
+    case M_SOF1:    /* Extended sequential, Huffman */
+      if (! get_sof(cinfo, JPROC_SEQUENTIAL, FALSE, DCTSIZE))
+  return JPEG_SUSPENDED;
+      break;
+
+    case M_SOF2:    /* Progressive, Huffman */
+      if (! get_sof(cinfo, JPROC_PROGRESSIVE, FALSE, DCTSIZE))
+  return JPEG_SUSPENDED;
+      break;
+
+    case M_SOF3:    /* Lossless, Huffman */
+      if (! get_sof(cinfo, JPROC_LOSSLESS, FALSE, 1))
+  return JPEG_SUSPENDED;
+      break;
+
+    case M_SOF9:    /* Extended sequential, arithmetic */
+      if (! get_sof(cinfo, JPROC_SEQUENTIAL, TRUE, DCTSIZE))
+  return JPEG_SUSPENDED;
+      break;
+
+    case M_SOF10:    /* Progressive, arithmetic */
+      if (! get_sof(cinfo, JPROC_PROGRESSIVE, TRUE, DCTSIZE))
+  return JPEG_SUSPENDED;
+      break;
+
+    case M_SOF11:    /* Lossless, arithmetic */
+      if (! get_sof(cinfo, JPROC_LOSSLESS, TRUE, 1))
+  return JPEG_SUSPENDED;
+      break;
+
+    /* Currently unsupported SOFn types */
+    case M_SOF5:    /* Differential sequential, Huffman */
+    case M_SOF6:    /* Differential progressive, Huffman */
+    case M_SOF7:    /* Differential lossless, Huffman */
+    case M_JPG:      /* Reserved for JPEG extensions */
+    case M_SOF13:    /* Differential sequential, arithmetic */
+    case M_SOF14:    /* Differential progressive, arithmetic */
+    case M_SOF15:    /* Differential lossless, arithmetic */
+      ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker);
+      break;
+
+    case M_SOS:
+      if (! get_sos(cinfo))
+  return JPEG_SUSPENDED;
+      cinfo->unread_marker = 0;  /* processed the marker */
+      return JPEG_REACHED_SOS;
+    
+    case M_EOI:
+      TRACEMS(cinfo, 1, JTRC_EOI);
+      cinfo->unread_marker = 0;  /* processed the marker */
+      return JPEG_REACHED_EOI;
+      
+    case M_DAC:
+      if (! get_dac(cinfo))
+  return JPEG_SUSPENDED;
+      break;
+      
+    case M_DHT:
+      if (! get_dht(cinfo))
+  return JPEG_SUSPENDED;
+      break;
+      
+    case M_DQT:
+      if (! get_dqt(cinfo))
+  return JPEG_SUSPENDED;
+      break;
+      
+    case M_DRI:
+      if (! get_dri(cinfo))
+  return JPEG_SUSPENDED;
+      break;
+      
+    case M_APP0:
+    case M_APP1:
+    case M_APP2:
+    case M_APP3:
+    case M_APP4:
+    case M_APP5:
+    case M_APP6:
+    case M_APP7:
+    case M_APP8:
+    case M_APP9:
+    case M_APP10:
+    case M_APP11:
+    case M_APP12:
+    case M_APP13:
+    case M_APP14:
+    case M_APP15:
+      if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[
+    cinfo->unread_marker - (int) M_APP0]) (cinfo))
+  return JPEG_SUSPENDED;
+      break;
+      
+    case M_COM:
+      if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo))
+  return JPEG_SUSPENDED;
+      break;
+
+    case M_RST0:    /* these are all parameterless */
+    case M_RST1:
+    case M_RST2:
+    case M_RST3:
+    case M_RST4:
+    case M_RST5:
+    case M_RST6:
+    case M_RST7:
+    case M_TEM:
+      TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker);
+      break;
+
+    case M_DNL:      /* Ignore DNL ... perhaps the wrong thing */
+      if (! skip_variable(cinfo))
+  return JPEG_SUSPENDED;
+      break;
+
+    default:      /* must be DHP, EXP, JPGn, or RESn */
+      /* For now, we treat the reserved markers as fatal errors since they are
+       * likely to be used to signal incompatible JPEG Part 3 extensions.
+       * Once the JPEG 3 version-number marker is well defined, this code
+       * ought to change!
+       */
+      ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
+      break;
+    }
+    /* Successfully processed marker, so reset state variable */
+    cinfo->unread_marker = 0;
+  } /* end loop */
+}
+
+
+/*
+ * Read a restart marker, which is expected to appear next in the datastream;
+ * if the marker is not there, take appropriate recovery action.
+ * Returns FALSE if suspension is required.
+ *
+ * This is called by the entropy decoder after it has read an appropriate
+ * number of MCUs.  cinfo->unread_marker may be nonzero if the entropy decoder
+ * has already read a marker from the data source.  Under normal conditions
+ * cinfo->unread_marker will be reset to 0 before returning; if not reset,
+ * it holds a marker which the decoder will be unable to read past.
+ */
+
+METHODDEF(boolean)
+read_restart_marker (j_decompress_ptr cinfo)
+{
+  /* Obtain a marker unless we already did. */
+  /* Note that next_marker will complain if it skips any data. */
+  if (cinfo->unread_marker == 0) {
+    if (! next_marker(cinfo))
+      return FALSE;
+  }
+
+  if (cinfo->unread_marker ==
+      ((int) M_RST0 + cinfo->marker->next_restart_num)) {
+    /* Normal case --- swallow the marker and let entropy decoder continue */
+    TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);
+    cinfo->unread_marker = 0;
+  } else {
+    /* Uh-oh, the restart markers have been messed up. */
+    /* Let the data source manager determine how to resync. */
+    if (! (*cinfo->src->resync_to_restart) (cinfo,
+              cinfo->marker->next_restart_num))
+      return FALSE;
+  }
+
+  /* Update next-restart state */
+  cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7;
+
+  return TRUE;
+}
+
+
+/*
+ * This is the default resync_to_restart method for data source managers
+ * to use if they don't have any better approach.  Some data source managers
+ * may be able to back up, or may have additional knowledge about the data
+ * which permits a more intelligent recovery strategy; such managers would
+ * presumably supply their own resync method.
+ *
+ * read_restart_marker calls resync_to_restart if it finds a marker other than
+ * the restart marker it was expecting.  (This code is *not* used unless
+ * a nonzero restart interval has been declared.)  cinfo->unread_marker is
+ * the marker code actually found (might be anything, except 0 or FF).
+ * The desired restart marker number (0..7) is passed as a parameter.
+ * This routine is supposed to apply whatever error recovery strategy seems
+ * appropriate in order to position the input stream to the next data segment.
+ * Note that cinfo->unread_marker is treated as a marker appearing before
+ * the current data-source input point; usually it should be reset to zero
+ * before returning.
+ * Returns FALSE if suspension is required.
+ *
+ * This implementation is substantially constrained by wanting to treat the
+ * input as a data stream; this means we can't back up.  Therefore, we have
+ * only the following actions to work with:
+ *   1. Simply discard the marker and let the entropy decoder resume at next
+ *      byte of file.
+ *   2. Read forward until we find another marker, discarding intervening
+ *      data.  (In theory we could look ahead within the current bufferload,
+ *      without having to discard data if we don't find the desired marker.
+ *      This idea is not implemented here, in part because it makes behavior
+ *      dependent on buffer size and chance buffer-boundary positions.)
+ *   3. Leave the marker unread (by failing to zero cinfo->unread_marker).
+ *      This will cause the entropy decoder to process an empty data segment,
+ *      inserting dummy zeroes, and then we will reprocess the marker.
+ *
+ * #2 is appropriate if we think the desired marker lies ahead, while #3 is
+ * appropriate if the found marker is a future restart marker (indicating
+ * that we have missed the desired restart marker, probably because it got
+ * corrupted).
+ * We apply #2 or #3 if the found marker is a restart marker no more than
+ * two counts behind or ahead of the expected one.  We also apply #2 if the
+ * found marker is not a legal JPEG marker code (it's certainly bogus data).
+ * If the found marker is a restart marker more than 2 counts away, we do #1
+ * (too much risk that the marker is erroneous; with luck we will be able to
+ * resync at some future point).
+ * For any valid non-restart JPEG marker, we apply #3.  This keeps us from
+ * overrunning the end of a scan.  An implementation limited to single-scan
+ * files might find it better to apply #2 for markers other than EOI, since
+ * any other marker would have to be bogus data in that case.
+ */
+
+GLOBAL(boolean)
+jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
+{
+  int marker = cinfo->unread_marker;
+  int action = 1;
+  
+  /* Always put up a warning. */
+  WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired);
+  
+  /* Outer loop handles repeated decision after scanning forward. */
+  for (;;) {
+    if (marker < (int) M_SOF0)
+      action = 2;    /* invalid marker */
+    else if (marker < (int) M_RST0 || marker > (int) M_RST7)
+      action = 3;    /* valid non-restart marker */
+    else {
+      if (marker == ((int) M_RST0 + ((desired+1) & 7)) ||
+    marker == ((int) M_RST0 + ((desired+2) & 7)))
+  action = 3;    /* one of the next two expected restarts */
+      else if (marker == ((int) M_RST0 + ((desired-1) & 7)) ||
+         marker == ((int) M_RST0 + ((desired-2) & 7)))
+  action = 2;    /* a prior restart, so advance */
+      else
+  action = 1;    /* desired restart or too far away */
+    }
+    TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action);
+    switch (action) {
+    case 1:
+      /* Discard marker and let entropy decoder resume processing. */
+      cinfo->unread_marker = 0;
+      return TRUE;
+    case 2:
+      /* Scan to the next marker, and repeat the decision loop. */
+      if (! next_marker(cinfo))
+  return FALSE;
+      marker = cinfo->unread_marker;
+      break;
+    case 3:
+      /* Return without advancing past this marker. */
+      /* Entropy decoder will be forced to process an empty segment. */
+      return TRUE;
+    }
+  } /* end loop */
+}
+
+
+/*
+ * Reset marker processing state to begin a fresh datastream.
+ */
+
+METHODDEF(void)
+reset_marker_reader (j_decompress_ptr cinfo)
+{
+  my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+  cinfo->comp_info = NULL;    /* until allocated by get_sof */
+  cinfo->input_scan_number = 0;    /* no SOS seen yet */
+  cinfo->unread_marker = 0;    /* no pending marker */
+  marker->pub.saw_SOI = FALSE;    /* set internal state too */
+  marker->pub.saw_SOF = FALSE;
+  marker->pub.discarded_bytes = 0;
+  marker->cur_marker = NULL;
+}
+
+
+/*
+ * Initialize the marker reader module.
+ * This is called only once, when the decompression object is created.
+ */
+
+GLOBAL(void)
+jinit_marker_reader (j_decompress_ptr cinfo)
+{
+  my_marker_ptr marker;
+  int i;
+
+  /* Create subobject in permanent pool */
+  marker = (my_marker_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+        SIZEOF(my_marker_reader));
+  cinfo->marker = (struct jpeg_marker_reader *) marker;
+  /* Initialize public method pointers */
+  marker->pub.reset_marker_reader = reset_marker_reader;
+  marker->pub.read_markers = read_markers;
+  marker->pub.read_restart_marker = read_restart_marker;
+  /* Initialize COM/APPn processing.
+   * By default, we examine and then discard APP0 and APP14,
+   * but simply discard COM and all other APPn.
+   */
+  marker->process_COM = skip_variable;
+  marker->length_limit_COM = 0;
+  for (i = 0; i < 16; i++) {
+    marker->process_APPn[i] = skip_variable;
+    marker->length_limit_APPn[i] = 0;
+  }
+  marker->process_APPn[0] = get_interesting_appn;
+  marker->process_APPn[14] = get_interesting_appn;
+  /* Reset marker processing state */
+  reset_marker_reader(cinfo);
+}
+
+
+/*
+ * Control saving of COM and APPn markers into marker_list.
+ */
+
+#ifdef SAVE_MARKERS_SUPPORTED
+
+GLOBAL(void)
+jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
+       unsigned int length_limit)
+{
+  my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+  long maxlength;
+  jpeg_marker_parser_method processor;
+
+  /* Length limit mustn't be larger than what we can allocate
+   * (should only be a concern in a 16-bit environment).
+   */
+  maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct);
+  if (((long) length_limit) > maxlength)
+    length_limit = (unsigned int) maxlength;
+
+  /* Choose processor routine to use.
+   * APP0/APP14 have special requirements.
+   */
+  if (length_limit) {
+    processor = save_marker;
+    /* If saving APP0/APP14, save at least enough for our internal use. */
+    if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN)
+      length_limit = APP0_DATA_LEN;
+    else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN)
+      length_limit = APP14_DATA_LEN;
+  } else {
+    processor = skip_variable;
+    /* If discarding APP0/APP14, use our regular on-the-fly processor. */
+    if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14)
+      processor = get_interesting_appn;
+  }
+
+  if (marker_code == (int) M_COM) {
+    marker->process_COM = processor;
+    marker->length_limit_COM = length_limit;
+  } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) {
+    marker->process_APPn[marker_code - (int) M_APP0] = processor;
+    marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit;
+  } else
+    ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
+}
+
+#endif /* SAVE_MARKERS_SUPPORTED */
+
+
+/*
+ * Install a special processing method for COM or APPn markers.
+ */
+
+GLOBAL(void)
+jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code,
+         jpeg_marker_parser_method routine)
+{
+  my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+  if (marker_code == (int) M_COM)
+    marker->process_COM = routine;
+  else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15)
+    marker->process_APPn[marker_code - (int) M_APP0] = routine;
+  else
+    ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdmaster.c b/Utilities/ITK/Utilities/itkjpeg/jdmaster.c
new file mode 100644
index 0000000000000000000000000000000000000000..cb06e011003c82847e666065c16d2ac738d59afa
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdmaster.c
@@ -0,0 +1,460 @@
+/*
+ * jdmaster.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains master control logic for the JPEG decompressor.
+ * These routines are concerned with selecting the modules to be executed
+ * and with determining the number of passes and the work to be done in each
+ * pass.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private state */
+
+typedef struct {
+  struct jpeg_decomp_master pub; /* public fields */
+
+  int pass_number;    /* # of passes completed */
+
+  boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
+
+  /* Saved references to initialized quantizer modules,
+   * in case we need to switch modes.
+   */
+  struct jpeg_color_quantizer * quantizer_1pass;
+  struct jpeg_color_quantizer * quantizer_2pass;
+} my_decomp_master;
+
+typedef my_decomp_master * my_master_ptr;
+
+
+/*
+ * Determine whether merged upsample/color conversion should be used.
+ * CRUCIAL: this must match the actual capabilities of jdmerge.c!
+ */
+
+LOCAL(boolean)
+use_merged_upsample (j_decompress_ptr cinfo)
+{
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+  /* Merging is the equivalent of plain box-filter upsampling */
+  if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling)
+    return FALSE;
+  /* jdmerge.c only supports YCC=>RGB color conversion */
+  if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
+      cinfo->out_color_space != JCS_RGB ||
+      cinfo->out_color_components != RGB_PIXELSIZE)
+    return FALSE;
+  /* and it only handles 2h1v or 2h2v sampling ratios */
+  if (cinfo->comp_info[0].h_samp_factor != 2 ||
+      cinfo->comp_info[1].h_samp_factor != 1 ||
+      cinfo->comp_info[2].h_samp_factor != 1 ||
+      cinfo->comp_info[0].v_samp_factor >  2 ||
+      cinfo->comp_info[1].v_samp_factor != 1 ||
+      cinfo->comp_info[2].v_samp_factor != 1)
+    return FALSE;
+  /* furthermore, it doesn't work if each component has been
+     processed differently */
+  if (cinfo->comp_info[0].codec_data_unit != cinfo->min_codec_data_unit ||
+      cinfo->comp_info[1].codec_data_unit != cinfo->min_codec_data_unit ||
+      cinfo->comp_info[2].codec_data_unit != cinfo->min_codec_data_unit)
+    return FALSE;
+  /* ??? also need to test for upsample-time rescaling, when & if supported */
+  return TRUE;      /* by golly, it'll work... */
+#else
+  return FALSE;
+#endif
+}
+
+
+/*
+ * Compute output image dimensions and related values.
+ * NOTE: this is exported for possible use by application.
+ * Hence it mustn't do anything that can't be done twice.
+ * Also note that it may be called before the master module is initialized!
+ */
+
+GLOBAL(void)
+jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
+/* Do computations that are needed before master selection phase */
+{
+  /* Prevent application from calling me at wrong times */
+  if (cinfo->global_state != DSTATE_READY)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  (*cinfo->codec->calc_output_dimensions) (cinfo);
+
+  /* Report number of components in selected colorspace. */
+  /* Probably this should be in the color conversion module... */
+  switch (cinfo->out_color_space) {
+  case JCS_GRAYSCALE:
+    cinfo->out_color_components = 1;
+    break;
+  case JCS_RGB:
+#if RGB_PIXELSIZE != 3
+    cinfo->out_color_components = RGB_PIXELSIZE;
+    break;
+#endif /* else share code with YCbCr */
+  case JCS_YCbCr:
+    cinfo->out_color_components = 3;
+    break;
+  case JCS_CMYK:
+  case JCS_YCCK:
+    cinfo->out_color_components = 4;
+    break;
+  default:      /* else must be same colorspace as in file */
+    cinfo->out_color_components = cinfo->num_components;
+    break;
+  }
+  cinfo->output_components = (cinfo->quantize_colors ? 1 :
+            cinfo->out_color_components);
+
+  /* See if upsampler will want to emit more than one row at a time */
+  if (use_merged_upsample(cinfo))
+    cinfo->rec_outbuf_height = cinfo->max_v_samp_factor;
+  else
+    cinfo->rec_outbuf_height = 1;
+}
+
+
+/*
+ * Several decompression processes need to range-limit values to the range
+ * 0..MAXJSAMPLE; the input value may fall somewhat outside this range
+ * due to noise introduced by quantization, roundoff error, etc.  These
+ * processes are inner loops and need to be as fast as possible.  On most
+ * machines, particularly CPUs with pipelines or instruction prefetch,
+ * a (subscript-check-less) C table lookup
+ *    x = sample_range_limit[x];
+ * is faster than explicit tests
+ *    if (x < 0)  x = 0;
+ *    else if (x > MAXJSAMPLE)  x = MAXJSAMPLE;
+ * These processes all use a common table prepared by the routine below.
+ *
+ * For most steps we can mathematically guarantee that the initial value
+ * of x is within MAXJSAMPLE+1 of the legal range, so a table running from
+ * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient.  But for the initial
+ * limiting step (just after the IDCT), a wildly out-of-range value is 
+ * possible if the input data is corrupt.  To avoid any chance of indexing
+ * off the end of memory and getting a bad-pointer trap, we perform the
+ * post-IDCT limiting thus:
+ *    x = range_limit[x & MASK];
+ * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
+ * samples.  Under normal circumstances this is more than enough range and
+ * a correct output will be generated; with bogus input data the mask will
+ * cause wraparound, and we will safely generate a bogus-but-in-range output.
+ * For the post-IDCT step, we want to convert the data from signed to unsigned
+ * representation by adding CENTERJSAMPLE at the same time that we limit it.
+ * So the post-IDCT limiting table ends up looking like this:
+ *   CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
+ *   MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
+ *   0          (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
+ *   0,1,...,CENTERJSAMPLE-1
+ * Negative inputs select values from the upper half of the table after
+ * masking.
+ *
+ * We can save some space by overlapping the start of the post-IDCT table
+ * with the simpler range limiting table.  The post-IDCT table begins at
+ * sample_range_limit + CENTERJSAMPLE.
+ *
+ * Note that the table is allocated in near data space on PCs; it's small
+ * enough and used often enough to justify this.
+ */
+
+LOCAL(void)
+prepare_range_limit_table (j_decompress_ptr cinfo)
+/* Allocate and fill in the sample_range_limit table */
+{
+  JSAMPLE * table;
+  int i;
+
+  table = (JSAMPLE *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+    (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
+  table += (MAXJSAMPLE+1);  /* allow negative subscripts of simple table */
+  cinfo->sample_range_limit = table;
+  /* First segment of "simple" table: limit[x] = 0 for x < 0 */
+  MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
+  /* Main part of "simple" table: limit[x] = x */
+  for (i = 0; i <= MAXJSAMPLE; i++)
+    table[i] = (JSAMPLE) i;
+  table += CENTERJSAMPLE;  /* Point to where post-IDCT table starts */
+  /* End of simple table, rest of first half of post-IDCT table */
+  for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
+    table[i] = MAXJSAMPLE;
+  /* Second half of post-IDCT table */
+  MEMZERO(table + (2 * (MAXJSAMPLE+1)),
+    (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
+  MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
+    cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
+}
+
+
+/*
+ * Master selection of decompression modules.
+ * This is done once at jpeg_start_decompress time.  We determine
+ * which modules will be used and give them appropriate initialization calls.
+ * We also initialize the decompressor input side to begin consuming data.
+ *
+ * Since jpeg_read_header has finished, we know what is in the SOF
+ * and (first) SOS markers.  We also have all the application parameter
+ * settings.
+ */
+
+LOCAL(void)
+master_selection (j_decompress_ptr cinfo)
+{
+  my_master_ptr master = (my_master_ptr) cinfo->master;
+  long samplesperrow;
+  JDIMENSION jd_samplesperrow;
+
+  /* Initialize dimensions and other stuff */
+  jpeg_calc_output_dimensions(cinfo);
+  prepare_range_limit_table(cinfo);
+
+  /* Width of an output scanline must be representable as JDIMENSION. */
+  samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
+  jd_samplesperrow = (JDIMENSION) samplesperrow;
+  if ((long) jd_samplesperrow != samplesperrow)
+    ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+  /* Initialize my private state */
+  master->pass_number = 0;
+  master->using_merged_upsample = use_merged_upsample(cinfo);
+
+  /* Color quantizer selection */
+  master->quantizer_1pass = NULL;
+  master->quantizer_2pass = NULL;
+  /* No mode changes if not using buffered-image mode. */
+  if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
+    cinfo->enable_1pass_quant = FALSE;
+    cinfo->enable_external_quant = FALSE;
+    cinfo->enable_2pass_quant = FALSE;
+  }
+  if (cinfo->quantize_colors) {
+    if (cinfo->raw_data_out)
+      ERREXIT(cinfo, JERR_NOTIMPL);
+    /* 2-pass quantizer only works in 3-component color space. */
+    if (cinfo->out_color_components != 3) {
+      cinfo->enable_1pass_quant = TRUE;
+      cinfo->enable_external_quant = FALSE;
+      cinfo->enable_2pass_quant = FALSE;
+      cinfo->colormap = NULL;
+    } else if (cinfo->colormap != NULL) {
+      cinfo->enable_external_quant = TRUE;
+    } else if (cinfo->two_pass_quantize) {
+      cinfo->enable_2pass_quant = TRUE;
+    } else {
+      cinfo->enable_1pass_quant = TRUE;
+    }
+
+    if (cinfo->enable_1pass_quant) {
+#ifdef QUANT_1PASS_SUPPORTED
+      jinit_1pass_quantizer(cinfo);
+      master->quantizer_1pass = cinfo->cquantize;
+#else
+      ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+    }
+
+    /* We use the 2-pass code to map to external colormaps. */
+    if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) {
+#ifdef QUANT_2PASS_SUPPORTED
+      jinit_2pass_quantizer(cinfo);
+      master->quantizer_2pass = cinfo->cquantize;
+#else
+      ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+    }
+    /* If both quantizers are initialized, the 2-pass one is left active;
+     * this is necessary for starting with quantization to an external map.
+     */
+  }
+
+  /* Post-processing: in particular, color conversion first */
+  if (! cinfo->raw_data_out) {
+    if (master->using_merged_upsample) {
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+      jinit_merged_upsampler(cinfo); /* does color conversion too */
+#else
+      ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+    } else {
+      jinit_color_deconverter(cinfo);
+      jinit_upsampler(cinfo);
+    }
+    jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
+  }
+
+  /* Initialize principal buffer controllers. */
+  if (! cinfo->raw_data_out)
+    jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
+
+  /* We can now tell the memory manager to allocate virtual arrays. */
+  (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+  /* Initialize input side of decompressor to consume first scan. */
+  (*cinfo->inputctl->start_input_pass) (cinfo);
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+  /* If jpeg_start_decompress will read the whole file, initialize
+   * progress monitoring appropriately.  The input step is counted
+   * as one pass.
+   */
+  if (cinfo->progress != NULL && ! cinfo->buffered_image &&
+      cinfo->inputctl->has_multiple_scans) {
+    int nscans;
+    /* Estimate number of scans to set pass_limit. */
+    if (cinfo->process == JPROC_PROGRESSIVE) {
+      /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
+      nscans = 2 + 3 * cinfo->num_components;
+    } else {
+      /* For a nonprogressive multiscan file, estimate 1 scan per component. */
+      nscans = cinfo->num_components;
+    }
+    cinfo->progress->pass_counter = 0L;
+    cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+    cinfo->progress->completed_passes = 0;
+    cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
+    /* Count the input pass as done */
+    master->pass_number++;
+  }
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+}
+
+
+/*
+ * Per-pass setup.
+ * This is called at the beginning of each output pass.  We determine which
+ * modules will be active during this pass and give them appropriate
+ * start_pass calls.  We also set is_dummy_pass to indicate whether this
+ * is a "real" output pass or a dummy pass for color quantization.
+ * (In the latter case, jdapistd.c will crank the pass to completion.)
+ */
+
+METHODDEF(void)
+prepare_for_output_pass (j_decompress_ptr cinfo)
+{
+  my_master_ptr master = (my_master_ptr) cinfo->master;
+
+  if (master->pub.is_dummy_pass) {
+#ifdef QUANT_2PASS_SUPPORTED
+    /* Final pass of 2-pass quantization */
+    master->pub.is_dummy_pass = FALSE;
+    (*cinfo->cquantize->start_pass) (cinfo, FALSE);
+    (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST);
+    (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST);
+#else
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* QUANT_2PASS_SUPPORTED */
+  } else {
+    if (cinfo->quantize_colors && cinfo->colormap == NULL) {
+      /* Select new quantization method */
+      if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) {
+  cinfo->cquantize = master->quantizer_2pass;
+  master->pub.is_dummy_pass = TRUE;
+      } else if (cinfo->enable_1pass_quant) {
+  cinfo->cquantize = master->quantizer_1pass;
+      } else {
+  ERREXIT(cinfo, JERR_MODE_CHANGE);
+      }
+    }
+    (*cinfo->codec->start_output_pass) (cinfo);
+    if (! cinfo->raw_data_out) {
+      if (! master->using_merged_upsample)
+  (*cinfo->cconvert->start_pass) (cinfo);
+      (*cinfo->upsample->start_pass) (cinfo);
+      if (cinfo->quantize_colors)
+  (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass);
+      (*cinfo->post->start_pass) (cinfo,
+      (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
+      (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
+    }
+  }
+
+  /* Set up progress monitor's pass info if present */
+  if (cinfo->progress != NULL) {
+    cinfo->progress->completed_passes = master->pass_number;
+    cinfo->progress->total_passes = master->pass_number +
+            (master->pub.is_dummy_pass ? 2 : 1);
+    /* In buffered-image mode, we assume one more output pass if EOI not
+     * yet reached, but no more passes if EOI has been reached.
+     */
+    if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
+      cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
+    }
+  }
+}
+
+
+/*
+ * Finish up at end of an output pass.
+ */
+
+METHODDEF(void)
+finish_output_pass (j_decompress_ptr cinfo)
+{
+  my_master_ptr master = (my_master_ptr) cinfo->master;
+
+  if (cinfo->quantize_colors)
+    (*cinfo->cquantize->finish_pass) (cinfo);
+  master->pass_number++;
+}
+
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Switch to a new external colormap between output passes.
+ */
+
+GLOBAL(void)
+jpeg_new_colormap (j_decompress_ptr cinfo)
+{
+  my_master_ptr master = (my_master_ptr) cinfo->master;
+
+  /* Prevent application from calling me at wrong times */
+  if (cinfo->global_state != DSTATE_BUFIMAGE)
+    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+  if (cinfo->quantize_colors && cinfo->enable_external_quant &&
+      cinfo->colormap != NULL) {
+    /* Select 2-pass quantizer for external colormap use */
+    cinfo->cquantize = master->quantizer_2pass;
+    /* Notify quantizer of colormap change */
+    (*cinfo->cquantize->new_color_map) (cinfo);
+    master->pub.is_dummy_pass = FALSE; /* just in case */
+  } else
+    ERREXIT(cinfo, JERR_MODE_CHANGE);
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+
+
+/*
+ * Initialize master decompression control and select active modules.
+ * This is performed at the start of jpeg_start_decompress.
+ */
+
+GLOBAL(void)
+jinit_master_decompress (j_decompress_ptr cinfo)
+{
+  my_master_ptr master;
+
+  master = (my_master_ptr)
+      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+          SIZEOF(my_decomp_master));
+  cinfo->master = (struct jpeg_decomp_master *) master;
+  master->pub.prepare_for_output_pass = prepare_for_output_pass;
+  master->pub.finish_output_pass = finish_output_pass;
+
+  master->pub.is_dummy_pass = FALSE;
+
+  master_selection(cinfo);
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdmerge.c b/Utilities/ITK/Utilities/itkjpeg/jdmerge.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a235959126955f8ac9f124e23972fbf76530ef7
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdmerge.c
@@ -0,0 +1,402 @@
+/*
+ * jdmerge.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains code for merged upsampling/color conversion.
+ *
+ * This file combines functions from jdsample.c and jdcolor.c;
+ * read those files first to understand what's going on.
+ *
+ * When the chroma components are to be upsampled by simple replication
+ * (ie, box filtering), we can save some work in color conversion by
+ * calculating all the output pixels corresponding to a pair of chroma
+ * samples at one time.  In the conversion equations
+ *  R = Y           + K1 * Cr
+ *  G = Y + K2 * Cb + K3 * Cr
+ *  B = Y + K4 * Cb
+ * only the Y term varies among the group of pixels corresponding to a pair
+ * of chroma samples, so the rest of the terms can be calculated just once.
+ * At typical sampling ratios, this eliminates half or three-quarters of the
+ * multiplications needed for color conversion.
+ *
+ * This file currently provides implementations for the following cases:
+ *  YCbCr => RGB color conversion only.
+ *  Sampling ratios of 2h1v or 2h2v.
+ *  No scaling needed at upsample time.
+ *  Corner-aligned (non-CCIR601) sampling alignment.
+ * Other special cases could be added, but in most applications these are
+ * the only common cases.  (For uncommon cases we fall back on the more
+ * general code in jdsample.c and jdcolor.c.)
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+
+
+/* Private subobject */
+
+typedef struct {
+  struct jpeg_upsampler pub;  /* public fields */
+
+  /* Pointer to routine to do actual upsampling/conversion of one row group */
+  JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
+         JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+         JSAMPARRAY output_buf));
+
+  /* Private state for YCC->RGB conversion */
+  int * Cr_r_tab;    /* => table for Cr to R conversion */
+  int * Cb_b_tab;    /* => table for Cb to B conversion */
+  INT32 * Cr_g_tab;    /* => table for Cr to G conversion */
+  INT32 * Cb_g_tab;    /* => table for Cb to G conversion */
+
+  /* For 2:1 vertical sampling, we produce two output rows at a time.
+   * We need a "spare" row buffer to hold the second output row if the
+   * application provides just a one-row buffer; we also use the spare
+   * to discard the dummy last row if the image height is odd.
+   */
+  JSAMPROW spare_row;
+  boolean spare_full;    /* T if spare buffer is occupied */
+
+  JDIMENSION out_row_width;  /* samples per output row */
+  JDIMENSION rows_to_go;  /* counts rows remaining in image */
+} my_upsampler;
+
+typedef my_upsampler * my_upsample_ptr;
+
+#define SCALEBITS  16  /* speediest right-shift on some machines */
+#define ONE_HALF  ((INT32) 1 << (SCALEBITS-1))
+#define FIX(x)    ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+
+/*
+ * Initialize tables for YCC->RGB colorspace conversion.
+ * This is taken directly from jdcolor.c; see that file for more info.
+ */
+
+LOCAL(void)
+build_ycc_rgb_table (j_decompress_ptr cinfo)
+{
+  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+  int i;
+  INT32 x;
+  SHIFT_TEMPS
+
+  upsample->Cr_r_tab = (int *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        (MAXJSAMPLE+1) * SIZEOF(int));
+  upsample->Cb_b_tab = (int *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        (MAXJSAMPLE+1) * SIZEOF(int));
+  upsample->Cr_g_tab = (INT32 *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        (MAXJSAMPLE+1) * SIZEOF(INT32));
+  upsample->Cb_g_tab = (INT32 *)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        (MAXJSAMPLE+1) * SIZEOF(INT32));
+
+  for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
+    /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
+    /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
+    /* Cr=>R value is nearest int to 1.40200 * x */
+    upsample->Cr_r_tab[i] = (int)
+        RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
+    /* Cb=>B value is nearest int to 1.77200 * x */
+    upsample->Cb_b_tab[i] = (int)
+        RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
+    /* Cr=>G value is scaled-up -0.71414 * x */
+    upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
+    /* Cb=>G value is scaled-up -0.34414 * x */
+    /* We also add in ONE_HALF so that need not do it in inner loop */
+    upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
+  }
+}
+
+
+/*
+ * Initialize for an upsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_merged_upsample (j_decompress_ptr cinfo)
+{
+  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+  /* Mark the spare buffer empty */
+  upsample->spare_full = FALSE;
+  /* Initialize total-height counter for detecting bottom of image */
+  upsample->rows_to_go = cinfo->output_height;
+}
+
+
+/*
+ * Control routine to do upsampling (and color conversion).
+ *
+ * The control routine just handles the row buffering considerations.
+ */
+
+METHODDEF(void)
+merged_2v_upsample (j_decompress_ptr cinfo,
+        JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+        JDIMENSION in_row_groups_avail,
+        JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+        JDIMENSION out_rows_avail)
+/* 2:1 vertical sampling case: may need a spare row. */
+{
+  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+  JSAMPROW work_ptrs[2];
+  JDIMENSION num_rows;    /* number of rows returned to caller */
+  (void)in_row_groups_avail;
+
+  if (upsample->spare_full) {
+    /* If we have a spare row saved from a previous cycle, just return it. */
+    jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
+          1, upsample->out_row_width);
+    num_rows = 1;
+    upsample->spare_full = FALSE;
+  } else {
+    /* Figure number of rows to return to caller. */
+    num_rows = 2;
+    /* Not more than the distance to the end of the image. */
+    if (num_rows > upsample->rows_to_go)
+      num_rows = upsample->rows_to_go;
+    /* And not more than what the client can accept: */
+    out_rows_avail -= *out_row_ctr;
+    if (num_rows > out_rows_avail)
+      num_rows = out_rows_avail;
+    /* Create output pointer array for upsampler. */
+    work_ptrs[0] = output_buf[*out_row_ctr];
+    if (num_rows > 1) {
+      work_ptrs[1] = output_buf[*out_row_ctr + 1];
+    } else {
+      work_ptrs[1] = upsample->spare_row;
+      upsample->spare_full = TRUE;
+    }
+    /* Now do the upsampling. */
+    (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
+  }
+
+  /* Adjust counts */
+  *out_row_ctr += num_rows;
+  upsample->rows_to_go -= num_rows;
+  /* When the buffer is emptied, declare this input row group consumed */
+  if (! upsample->spare_full)
+    (*in_row_group_ctr)++;
+}
+
+
+METHODDEF(void)
+merged_1v_upsample (j_decompress_ptr cinfo,
+        JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+        JDIMENSION in_row_groups_avail,
+        JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+        JDIMENSION out_rows_avail)
+/* 1:1 vertical sampling case: much easier, never need a spare row. */
+{
+  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+  (void)in_row_groups_avail;(void)out_rows_avail;
+
+  /* Just do the upsampling. */
+  (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
+       output_buf + *out_row_ctr);
+  /* Adjust counts */
+  (*out_row_ctr)++;
+  (*in_row_group_ctr)++;
+}
+
+
+/*
+ * These are the routines invoked by the control routines to do
+ * the actual upsampling/conversion.  One row group is processed per call.
+ *
+ * Note: since we may be writing directly into application-supplied buffers,
+ * we have to be honest about the output width; we can't assume the buffer
+ * has been rounded up to an even width.
+ */
+
+
+/*
+ * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
+ */
+
+METHODDEF(void)
+h2v1_merged_upsample (j_decompress_ptr cinfo,
+          JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+          JSAMPARRAY output_buf)
+{
+  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+  register int y, cred, cgreen, cblue;
+  int cb, cr;
+  register JSAMPROW outptr;
+  JSAMPROW inptr0, inptr1, inptr2;
+  JDIMENSION col;
+  /* copy these pointers into registers if possible */
+  register JSAMPLE * range_limit = cinfo->sample_range_limit;
+  int * Crrtab = upsample->Cr_r_tab;
+  int * Cbbtab = upsample->Cb_b_tab;
+  INT32 * Crgtab = upsample->Cr_g_tab;
+  INT32 * Cbgtab = upsample->Cb_g_tab;
+  SHIFT_TEMPS
+
+  inptr0 = input_buf[0][in_row_group_ctr];
+  inptr1 = input_buf[1][in_row_group_ctr];
+  inptr2 = input_buf[2][in_row_group_ctr];
+  outptr = output_buf[0];
+  /* Loop for each pair of output pixels */
+  for (col = cinfo->output_width >> 1; col > 0; col--) {
+    /* Do the chroma part of the calculation */
+    cb = GETJSAMPLE(*inptr1++);
+    cr = GETJSAMPLE(*inptr2++);
+    cred = Crrtab[cr];
+    cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+    cblue = Cbbtab[cb];
+    /* Fetch 2 Y values and emit 2 pixels */
+    y  = GETJSAMPLE(*inptr0++);
+    outptr[RGB_RED] =   range_limit[y + cred];
+    outptr[RGB_GREEN] = range_limit[y + cgreen];
+    outptr[RGB_BLUE] =  range_limit[y + cblue];
+    outptr += RGB_PIXELSIZE;
+    y  = GETJSAMPLE(*inptr0++);
+    outptr[RGB_RED] =   range_limit[y + cred];
+    outptr[RGB_GREEN] = range_limit[y + cgreen];
+    outptr[RGB_BLUE] =  range_limit[y + cblue];
+    outptr += RGB_PIXELSIZE;
+  }
+  /* If image width is odd, do the last output column separately */
+  if (cinfo->output_width & 1) {
+    cb = GETJSAMPLE(*inptr1);
+    cr = GETJSAMPLE(*inptr2);
+    cred = Crrtab[cr];
+    cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+    cblue = Cbbtab[cb];
+    y  = GETJSAMPLE(*inptr0);
+    outptr[RGB_RED] =   range_limit[y + cred];
+    outptr[RGB_GREEN] = range_limit[y + cgreen];
+    outptr[RGB_BLUE] =  range_limit[y + cblue];
+  }
+}
+
+
+/*
+ * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
+ */
+
+METHODDEF(void)
+h2v2_merged_upsample (j_decompress_ptr cinfo,
+          JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+          JSAMPARRAY output_buf)
+{
+  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+  register int y, cred, cgreen, cblue;
+  int cb, cr;
+  register JSAMPROW outptr0, outptr1;
+  JSAMPROW inptr00, inptr01, inptr1, inptr2;
+  JDIMENSION col;
+  /* copy these pointers into registers if possible */
+  register JSAMPLE * range_limit = cinfo->sample_range_limit;
+  int * Crrtab = upsample->Cr_r_tab;
+  int * Cbbtab = upsample->Cb_b_tab;
+  INT32 * Crgtab = upsample->Cr_g_tab;
+  INT32 * Cbgtab = upsample->Cb_g_tab;
+  SHIFT_TEMPS
+
+  inptr00 = input_buf[0][in_row_group_ctr*2];
+  inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
+  inptr1 = input_buf[1][in_row_group_ctr];
+  inptr2 = input_buf[2][in_row_group_ctr];
+  outptr0 = output_buf[0];
+  outptr1 = output_buf[1];
+  /* Loop for each group of output pixels */
+  for (col = cinfo->output_width >> 1; col > 0; col--) {
+    /* Do the chroma part of the calculation */
+    cb = GETJSAMPLE(*inptr1++);
+    cr = GETJSAMPLE(*inptr2++);
+    cred = Crrtab[cr];
+    cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+    cblue = Cbbtab[cb];
+    /* Fetch 4 Y values and emit 4 pixels */
+    y  = GETJSAMPLE(*inptr00++);
+    outptr0[RGB_RED] =   range_limit[y + cred];
+    outptr0[RGB_GREEN] = range_limit[y + cgreen];
+    outptr0[RGB_BLUE] =  range_limit[y + cblue];
+    outptr0 += RGB_PIXELSIZE;
+    y  = GETJSAMPLE(*inptr00++);
+    outptr0[RGB_RED] =   range_limit[y + cred];
+    outptr0[RGB_GREEN] = range_limit[y + cgreen];
+    outptr0[RGB_BLUE] =  range_limit[y + cblue];
+    outptr0 += RGB_PIXELSIZE;
+    y  = GETJSAMPLE(*inptr01++);
+    outptr1[RGB_RED] =   range_limit[y + cred];
+    outptr1[RGB_GREEN] = range_limit[y + cgreen];
+    outptr1[RGB_BLUE] =  range_limit[y + cblue];
+    outptr1 += RGB_PIXELSIZE;
+    y  = GETJSAMPLE(*inptr01++);
+    outptr1[RGB_RED] =   range_limit[y + cred];
+    outptr1[RGB_GREEN] = range_limit[y + cgreen];
+    outptr1[RGB_BLUE] =  range_limit[y + cblue];
+    outptr1 += RGB_PIXELSIZE;
+  }
+  /* If image width is odd, do the last output column separately */
+  if (cinfo->output_width & 1) {
+    cb = GETJSAMPLE(*inptr1);
+    cr = GETJSAMPLE(*inptr2);
+    cred = Crrtab[cr];
+    cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+    cblue = Cbbtab[cb];
+    y  = GETJSAMPLE(*inptr00);
+    outptr0[RGB_RED] =   range_limit[y + cred];
+    outptr0[RGB_GREEN] = range_limit[y + cgreen];
+    outptr0[RGB_BLUE] =  range_limit[y + cblue];
+    y  = GETJSAMPLE(*inptr01);
+    outptr1[RGB_RED] =   range_limit[y + cred];
+    outptr1[RGB_GREEN] = range_limit[y + cgreen];
+    outptr1[RGB_BLUE] =  range_limit[y + cblue];
+  }
+}
+
+
+/*
+ * Module initialization routine for merged upsampling/color conversion.
+ *
+ * NB: this is called under the conditions determined by use_merged_upsample()
+ * in jdmaster.c.  That routine MUST correspond to the actual capabilities
+ * of this module; no safety checks are made here.
+ */
+
+GLOBAL(void)
+jinit_merged_upsampler (j_decompress_ptr cinfo)
+{
+  my_upsample_ptr upsample;
+
+  upsample = (my_upsample_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_upsampler));
+  cinfo->upsample = (struct jpeg_upsampler *) upsample;
+  upsample->pub.start_pass = start_pass_merged_upsample;
+  upsample->pub.need_context_rows = FALSE;
+
+  upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
+
+  if (cinfo->max_v_samp_factor == 2) {
+    upsample->pub.upsample = merged_2v_upsample;
+    upsample->upmethod = h2v2_merged_upsample;
+    /* Allocate a spare row buffer */
+    upsample->spare_row = (JSAMPROW)
+      (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+    (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
+  } else {
+    upsample->pub.upsample = merged_1v_upsample;
+    upsample->upmethod = h2v1_merged_upsample;
+    /* No spare row needed */
+    upsample->spare_row = NULL;
+  }
+
+  build_ycc_rgb_table(cinfo);
+}
+
+#endif /* UPSAMPLE_MERGING_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdphuff.c b/Utilities/ITK/Utilities/itkjpeg/jdphuff.c
new file mode 100644
index 0000000000000000000000000000000000000000..7baaff921518a91ab846def6f1b3fdbbedc4f1d4
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdphuff.c
@@ -0,0 +1,675 @@
+/*
+ * jdphuff.c
+ *
+ * Copyright (C) 1995-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines for progressive JPEG.
+ *
+ * Much of the complexity here has to do with supporting input suspension.
+ * If the data source module demands suspension, we want to be able to back
+ * up to the start of the current MCU.  To do this, we copy state variables
+ * into local working storage, and update them back to the permanent
+ * storage only upon successful completion of an MCU.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"    /* Private declarations for lossy subsystem */
+#include "jdhuff.h"    /* Declarations shared with jd*huff.c */
+
+
+#ifdef D_PROGRESSIVE_SUPPORTED
+
+/*
+ * Private entropy decoder object for progressive Huffman decoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+  unsigned int EOBRUN;      /* remaining EOBs in EOBRUN */
+  int last_dc_val[MAX_COMPS_IN_SCAN];  /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment.  You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src)  ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src)  \
+  ((dest).EOBRUN = (src).EOBRUN, \
+   (dest).last_dc_val[0] = (src).last_dc_val[0], \
+   (dest).last_dc_val[1] = (src).last_dc_val[1], \
+   (dest).last_dc_val[2] = (src).last_dc_val[2], \
+   (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+  huffd_common_fields;    /* Fields shared with other entropy decoders */
+
+  /* These fields are loaded into local variables at start of each MCU.
+   * In case of suspension, we exit WITHOUT updating them.
+   */
+  savable_state saved;    /* Other state at start of MCU */
+
+  /* These fields are NOT loaded into local working state. */
+  unsigned int restarts_to_go;  /* MCUs left in this restart interval */
+
+  /* Pointers to derived tables (these workspaces have image lifespan) */
+  d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+  d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */
+} phuff_entropy_decoder;
+
+typedef phuff_entropy_decoder * phuff_entropy_ptr;
+
+/* Forward declarations */
+METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo,
+              JBLOCKROW *MCU_data));
+METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo,
+              JBLOCKROW *MCU_data));
+METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo,
+               JBLOCKROW *MCU_data));
+METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo,
+               JBLOCKROW *MCU_data));
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass_phuff_decoder (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+  boolean is_DC_band, bad;
+  int ci, coefi, tbl;
+  int *coef_bit_ptr;
+  jpeg_component_info * compptr;
+
+  is_DC_band = (cinfo->Ss == 0);
+
+  /* Validate scan parameters */
+  bad = FALSE;
+  if (is_DC_band) {
+    if (cinfo->Se != 0)
+      bad = TRUE;
+  } else {
+    /* need not check Ss/Se < 0 since they came from unsigned bytes */
+    if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2)
+      bad = TRUE;
+    /* AC scans may have only one component */
+    if (cinfo->comps_in_scan != 1)
+      bad = TRUE;
+  }
+  if (cinfo->Ah != 0) {
+    /* Successive approximation refinement scan: must have Al = Ah-1. */
+    if (cinfo->Al != cinfo->Ah-1)
+      bad = TRUE;
+  }
+  if (cinfo->Al > 13)    /* need not check for < 0 */
+    bad = TRUE;
+  /* Arguably the maximum Al value should be less than 13 for 8-bit precision,
+   * but the spec doesn't say so, and we try to be liberal about what we
+   * accept.  Note: large Al values could result in out-of-range DC
+   * coefficients during early scans, leading to bizarre displays due to
+   * overflows in the IDCT math.  But we won't crash.
+   */
+  if (bad)
+    ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
+       cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
+  /* Update progression status, and verify that scan order is legal.
+   * Note that inter-scan inconsistencies are treated as warnings
+   * not fatal errors ... not clear if this is right way to behave.
+   */
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    int cindex = cinfo->cur_comp_info[ci]->component_index;
+    coef_bit_ptr = & cinfo->coef_bits[cindex][0];
+    if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
+      WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
+    for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
+      int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
+      if (cinfo->Ah != expected)
+  WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi);
+      coef_bit_ptr[coefi] = cinfo->Al;
+    }
+  }
+
+  /* Select MCU decoding routine */
+  if (cinfo->Ah == 0) {
+    if (is_DC_band)
+      lossyd->entropy_decode_mcu = decode_mcu_DC_first;
+    else
+      lossyd->entropy_decode_mcu = decode_mcu_AC_first;
+  } else {
+    if (is_DC_band)
+      lossyd->entropy_decode_mcu = decode_mcu_DC_refine;
+    else
+      lossyd->entropy_decode_mcu = decode_mcu_AC_refine;
+  }
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    /* Make sure requested tables are present, and compute derived tables.
+     * We may build same derived table more than once, but it's not expensive.
+     */
+    if (is_DC_band) {
+      if (cinfo->Ah == 0) {  /* DC refinement needs no table */
+  tbl = compptr->dc_tbl_no;
+  jpeg_make_d_derived_tbl(cinfo, TRUE, tbl,
+        & entropy->derived_tbls[tbl]);
+      }
+    } else {
+      tbl = compptr->ac_tbl_no;
+      jpeg_make_d_derived_tbl(cinfo, FALSE, tbl,
+            & entropy->derived_tbls[tbl]);
+      /* remember the single active table */
+      entropy->ac_derived_tbl = entropy->derived_tbls[tbl];
+    }
+    /* Initialize DC predictions to 0 */
+    entropy->saved.last_dc_val[ci] = 0;
+  }
+
+  /* Initialize bitread state variables */
+  entropy->bitstate.bits_left = 0;
+  entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+  entropy->insufficient_data = FALSE;
+
+  /* Initialize private state variables */
+  entropy->saved.EOBRUN = 0;
+
+  /* Initialize restart counter */
+  entropy->restarts_to_go = cinfo->restart_interval;
+}
+
+
+/*
+ * Figure F.12: extend sign bit.
+ * On some machines, a shift and add will be faster than a table lookup.
+ */
+
+#ifdef AVOID_TABLES
+
+#define HUFF_EXTEND(x,s)  ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
+
+#else
+
+#define HUFF_EXTEND(x,s)  ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+
+static const int extend_test[16] =   /* entry n is 2**(n-1) */
+  { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+    0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+
+static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
+  { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
+    ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
+    ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
+    ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+
+#endif /* AVOID_TABLES */
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ * Returns FALSE if must suspend.
+ */
+
+LOCAL(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+  int ci;
+
+  /* Throw away any unused bits remaining in bit buffer; */
+  /* include any full bytes in next_marker's count of discarded bytes */
+  cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
+  entropy->bitstate.bits_left = 0;
+
+  /* Advance past the RSTn marker */
+  if (! (*cinfo->marker->read_restart_marker) (cinfo))
+    return FALSE;
+
+  /* Re-initialize DC predictions to 0 */
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+    entropy->saved.last_dc_val[ci] = 0;
+  /* Re-init EOB run count, too */
+  entropy->saved.EOBRUN = 0;
+
+  /* Reset restart counter */
+  entropy->restarts_to_go = cinfo->restart_interval;
+
+  /* Reset out-of-data flag, unless read_restart_marker left us smack up
+   * against a marker.  In that case we will end up treating the next data
+   * segment as empty, and we can avoid producing bogus output pixels by
+   * leaving the flag set.
+   */
+  if (cinfo->unread_marker == 0)
+    entropy->insufficient_data = FALSE;
+
+  return TRUE;
+}
+
+
+/*
+ * Huffman MCU decoding.
+ * Each of these routines decodes and returns one MCU's worth of
+ * Huffman-compressed coefficients. 
+ * The coefficients are reordered from zigzag order into natural array order,
+ * but are not dequantized.
+ *
+ * The i'th block of the MCU is stored into the block pointed to by
+ * MCU_data[i].  WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
+ *
+ * We return FALSE if data source requested suspension.  In that case no
+ * changes have been made to permanent state.  (Exception: some output
+ * coefficients may already have been assigned.  This is harmless for
+ * spectral selection, since we'll just re-assign them on the next call.
+ * Successive approximation AC refinement has to be more careful, however.)
+ */
+
+/*
+ * MCU decoding for DC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{   
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+  int Al = cinfo->Al;
+  register int s, r;
+  int blkn, ci;
+  JBLOCKROW block;
+  BITREAD_STATE_VARS;
+  savable_state state;
+  d_derived_tbl * tbl;
+  jpeg_component_info * compptr;
+
+  /* Process restart marker if needed; may have to suspend */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0)
+      if (! process_restart(cinfo))
+  return FALSE;
+  }
+
+  /* If we've run out of data, just leave the MCU set to zeroes.
+   * This way, we return uniform gray for the remainder of the segment.
+   */
+  if (! entropy->insufficient_data) {
+
+    /* Load up working state */
+    BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+    ASSIGN_STATE(state, entropy->saved);
+
+    /* Outer loop handles each block in the MCU */
+
+    for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+      block = MCU_data[blkn];
+      ci = cinfo->MCU_membership[blkn];
+      compptr = cinfo->cur_comp_info[ci];
+      tbl = entropy->derived_tbls[compptr->dc_tbl_no];
+
+      /* Decode a single block's worth of coefficients */
+
+      /* Section F.2.2.1: decode the DC coefficient difference */
+      HUFF_DECODE(s, br_state, tbl, return FALSE, label1);
+      if (s) {
+  CHECK_BIT_BUFFER(br_state, s, return FALSE);
+  r = GET_BITS(s);
+  s = HUFF_EXTEND(r, s);
+      }
+
+      /* Convert DC difference to actual value, update last_dc_val */
+      s += state.last_dc_val[ci];
+      state.last_dc_val[ci] = s;
+      /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
+      (*block)[0] = (JCOEF) (s << Al);
+    }
+
+    /* Completed MCU, so update state */
+    BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+    ASSIGN_STATE(entropy->saved, state);
+  }
+
+  /* Account for restart interval (no-op if not using restarts) */
+  entropy->restarts_to_go--;
+
+  return TRUE;
+}
+
+
+/*
+ * MCU decoding for AC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{   
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+  int Se = cinfo->Se;
+  int Al = cinfo->Al;
+  register int s, k, r;
+  unsigned int EOBRUN;
+  JBLOCKROW block;
+  BITREAD_STATE_VARS;
+  d_derived_tbl * tbl;
+
+  /* Process restart marker if needed; may have to suspend */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0)
+      if (! process_restart(cinfo))
+  return FALSE;
+  }
+
+  /* If we've run out of data, just leave the MCU set to zeroes.
+   * This way, we return uniform gray for the remainder of the segment.
+   */
+  if (! entropy->insufficient_data) {
+
+    /* Load up working state.
+     * We can avoid loading/saving bitread state if in an EOB run.
+     */
+    EOBRUN = entropy->saved.EOBRUN;  /* only part of saved state we need */
+
+    /* There is always only one block per MCU */
+
+    if (EOBRUN > 0)    /* if it's a band of zeroes... */
+      EOBRUN--;      /* ...process it now (we do nothing) */
+    else {
+      BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+      block = MCU_data[0];
+      tbl = entropy->ac_derived_tbl;
+
+      for (k = cinfo->Ss; k <= Se; k++) {
+  HUFF_DECODE(s, br_state, tbl, return FALSE, label2);
+  r = s >> 4;
+  s &= 15;
+  if (s) {
+    k += r;
+    CHECK_BIT_BUFFER(br_state, s, return FALSE);
+    r = GET_BITS(s);
+    s = HUFF_EXTEND(r, s);
+    /* Scale and output coefficient in natural (dezigzagged) order */
+    (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al);
+  } else {
+    if (r == 15) {  /* ZRL */
+      k += 15;    /* skip 15 zeroes in band */
+    } else {    /* EOBr, run length is 2^r + appended bits */
+      EOBRUN = 1 << r;
+      if (r) {    /* EOBr, r > 0 */
+        CHECK_BIT_BUFFER(br_state, r, return FALSE);
+        r = GET_BITS(r);
+        EOBRUN += r;
+      }
+      EOBRUN--;    /* this band is processed at this moment */
+      break;    /* force end-of-band */
+    }
+  }
+      }
+
+      BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+    }
+
+    /* Completed MCU, so update state */
+    entropy->saved.EOBRUN = EOBRUN;  /* only part of saved state we need */
+  }
+
+  /* Account for restart interval (no-op if not using restarts) */
+  entropy->restarts_to_go--;
+
+  return TRUE;
+}
+
+
+/*
+ * MCU decoding for DC successive approximation refinement scan.
+ * Note: we assume such scans can be multi-component, although the spec
+ * is not very clear on the point.
+ */
+
+METHODDEF(boolean)
+decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{   
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+  int p1 = 1 << cinfo->Al;  /* 1 in the bit position being coded */
+  int blkn;
+  JBLOCKROW block;
+  BITREAD_STATE_VARS;
+
+  /* Process restart marker if needed; may have to suspend */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0)
+      if (! process_restart(cinfo))
+  return FALSE;
+  }
+
+  /* Not worth the cycles to check insufficient_data here,
+   * since we will not change the data anyway if we read zeroes.
+   */
+
+  /* Load up working state */
+  BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+
+  /* Outer loop handles each block in the MCU */
+
+  for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+    block = MCU_data[blkn];
+
+    /* Encoded data is simply the next bit of the two's-complement DC value */
+    CHECK_BIT_BUFFER(br_state, 1, return FALSE);
+    if (GET_BITS(1))
+      (*block)[0] |= p1;
+    /* Note: since we use |=, repeating the assignment later is safe */
+  }
+
+  /* Completed MCU, so update state */
+  BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+
+  /* Account for restart interval (no-op if not using restarts) */
+  entropy->restarts_to_go--;
+
+  return TRUE;
+}
+
+
+/*
+ * MCU decoding for AC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{   
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+  int Se = cinfo->Se;
+  int p1 = 1 << cinfo->Al;  /* 1 in the bit position being coded */
+  int m1 = (-1) << cinfo->Al;  /* -1 in the bit position being coded */
+  register int s, k, r;
+  unsigned int EOBRUN;
+  JBLOCKROW block;
+  JCOEFPTR thiscoef;
+  BITREAD_STATE_VARS;
+  d_derived_tbl * tbl;
+  int num_newnz;
+  int newnz_pos[DCTSIZE2];
+
+  /* Process restart marker if needed; may have to suspend */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0)
+      if (! process_restart(cinfo))
+  return FALSE;
+  }
+
+  /* If we've run out of data, don't modify the MCU.
+   */
+  if (! entropy->insufficient_data) {
+
+    /* Load up working state */
+    BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+    EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
+
+    /* There is always only one block per MCU */
+    block = MCU_data[0];
+    tbl = entropy->ac_derived_tbl;
+
+    /* If we are forced to suspend, we must undo the assignments to any newly
+     * nonzero coefficients in the block, because otherwise we'd get confused
+     * next time about which coefficients were already nonzero.
+     * But we need not undo addition of bits to already-nonzero coefficients;
+     * instead, we can test the current bit to see if we already did it.
+     */
+    num_newnz = 0;
+
+    /* initialize coefficient loop counter to start of band */
+    k = cinfo->Ss;
+
+    if (EOBRUN == 0) {
+      for (; k <= Se; k++) {
+  HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
+  r = s >> 4;
+  s &= 15;
+  if (s) {
+    if (s != 1)    /* size of new coef should always be 1 */
+      WARNMS(cinfo, JWRN_HUFF_BAD_CODE);
+    CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+    if (GET_BITS(1))
+      s = p1;    /* newly nonzero coef is positive */
+    else
+      s = m1;    /* newly nonzero coef is negative */
+  } else {
+    if (r != 15) {
+      EOBRUN = 1 << r;  /* EOBr, run length is 2^r + appended bits */
+      if (r) {
+        CHECK_BIT_BUFFER(br_state, r, goto undoit);
+        r = GET_BITS(r);
+        EOBRUN += r;
+      }
+      break;    /* rest of block is handled by EOB logic */
+    }
+    /* note s = 0 for processing ZRL */
+  }
+  /* Advance over already-nonzero coefs and r still-zero coefs,
+   * appending correction bits to the nonzeroes.  A correction bit is 1
+   * if the absolute value of the coefficient must be increased.
+   */
+  do {
+    thiscoef = *block + jpeg_natural_order[k];
+    if (*thiscoef != 0) {
+      CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+      if (GET_BITS(1)) {
+        if ((*thiscoef & p1) == 0) { /* do nothing if already set it */
+    if (*thiscoef >= 0)
+      *thiscoef += p1;
+    else
+      *thiscoef += m1;
+        }
+      }
+    } else {
+      if (--r < 0)
+        break;    /* reached target zero coefficient */
+    }
+    k++;
+  } while (k <= Se);
+  if (s) {
+    int pos = jpeg_natural_order[k];
+    /* Output newly nonzero coefficient */
+    (*block)[pos] = (JCOEF) s;
+    /* Remember its position in case we have to suspend */
+    newnz_pos[num_newnz++] = pos;
+  }
+      }
+    }
+
+    if (EOBRUN > 0) {
+      /* Scan any remaining coefficient positions after the end-of-band
+       * (the last newly nonzero coefficient, if any).  Append a correction
+       * bit to each already-nonzero coefficient.  A correction bit is 1
+       * if the absolute value of the coefficient must be increased.
+       */
+      for (; k <= Se; k++) {
+  thiscoef = *block + jpeg_natural_order[k];
+  if (*thiscoef != 0) {
+    CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+    if (GET_BITS(1)) {
+      if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */
+        if (*thiscoef >= 0)
+    *thiscoef += p1;
+        else
+    *thiscoef += m1;
+      }
+    }
+  }
+      }
+      /* Count one block completed in EOB run */
+      EOBRUN--;
+    }
+
+    /* Completed MCU, so update state */
+    BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+    entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
+  }
+
+  /* Account for restart interval (no-op if not using restarts) */
+  entropy->restarts_to_go--;
+
+  return TRUE;
+
+undoit:
+  /* Re-zero any output coefficients that we made newly nonzero */
+  while (num_newnz > 0)
+    (*block)[newnz_pos[--num_newnz]] = 0;
+
+  return FALSE;
+}
+
+
+/*
+ * Module initialization routine for progressive Huffman entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_phuff_decoder (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  phuff_entropy_ptr entropy;
+  int *coef_bit_ptr;
+  int ci, i;
+
+  entropy = (phuff_entropy_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(phuff_entropy_decoder));
+  lossyd->entropy_private = (void *) entropy;
+  lossyd->entropy_start_pass = start_pass_phuff_decoder;
+
+  /* Mark derived tables unallocated */
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    entropy->derived_tbls[i] = NULL;
+  }
+
+  /* Create progression status table */
+  cinfo->coef_bits = (int (*)[DCTSIZE2])
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        cinfo->num_components*DCTSIZE2*SIZEOF(int));
+  coef_bit_ptr = & cinfo->coef_bits[0][0];
+  for (ci = 0; ci < cinfo->num_components; ci++) 
+    for (i = 0; i < DCTSIZE2; i++)
+      *coef_bit_ptr++ = -1;
+}
+
+#endif /* D_PROGRESSIVE_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdpostct.c b/Utilities/ITK/Utilities/itkjpeg/jdpostct.c
new file mode 100644
index 0000000000000000000000000000000000000000..760eb19abd0d0c93b0cd738d64b608865ce3699e
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdpostct.c
@@ -0,0 +1,292 @@
+/*
+ * jdpostct.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the decompression postprocessing controller.
+ * This controller manages the upsampling, color conversion, and color
+ * quantization/reduction steps; specifically, it controls the buffering
+ * between upsample/color conversion and color quantization/reduction.
+ *
+ * If no color quantization/reduction is required, then this module has no
+ * work to do, and it just hands off to the upsample/color conversion code.
+ * An integrated upsample/convert/quantize process would replace this module
+ * entirely.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private buffer controller object */
+
+typedef struct {
+  struct jpeg_d_post_controller pub; /* public fields */
+
+  /* Color quantization source buffer: this holds output data from
+   * the upsample/color conversion step to be passed to the quantizer.
+   * For two-pass color quantization, we need a full-image buffer;
+   * for one-pass operation, a strip buffer is sufficient.
+   */
+  jvirt_sarray_ptr whole_image;  /* virtual array, or NULL if one-pass */
+  JSAMPARRAY buffer;    /* strip buffer, or current strip of virtual */
+  JDIMENSION strip_height;  /* buffer size in rows */
+  /* for two-pass mode only: */
+  JDIMENSION starting_row;  /* row # of first row in current strip */
+  JDIMENSION next_row;    /* index of next row to fill/empty in strip */
+} my_post_controller;
+
+typedef my_post_controller * my_post_ptr;
+
+
+/* Forward declarations */
+METHODDEF(void) post_process_1pass
+  JPP((j_decompress_ptr cinfo,
+       JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+       JDIMENSION in_row_groups_avail,
+       JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+       JDIMENSION out_rows_avail));
+#ifdef QUANT_2PASS_SUPPORTED
+METHODDEF(void) post_process_prepass
+  JPP((j_decompress_ptr cinfo,
+       JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+       JDIMENSION in_row_groups_avail,
+       JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+       JDIMENSION out_rows_avail));
+METHODDEF(void) post_process_2pass
+  JPP((j_decompress_ptr cinfo,
+       JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+       JDIMENSION in_row_groups_avail,
+       JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+       JDIMENSION out_rows_avail));
+#endif
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+  my_post_ptr post = (my_post_ptr) cinfo->post;
+
+  switch (pass_mode) {
+  case JBUF_PASS_THRU:
+    if (cinfo->quantize_colors) {
+      /* Single-pass processing with color quantization. */
+      post->pub.post_process_data = post_process_1pass;
+      /* We could be doing buffered-image output before starting a 2-pass
+       * color quantization; in that case, jinit_d_post_controller did not
+       * allocate a strip buffer.  Use the virtual-array buffer as workspace.
+       */
+      if (post->buffer == NULL) {
+  post->buffer = (*cinfo->mem->access_virt_sarray)
+    ((j_common_ptr) cinfo, post->whole_image,
+     (JDIMENSION) 0, post->strip_height, TRUE);
+      }
+    } else {
+      /* For single-pass processing without color quantization,
+       * I have no work to do; just call the upsampler directly.
+       */
+      post->pub.post_process_data = cinfo->upsample->upsample;
+    }
+    break;
+#ifdef QUANT_2PASS_SUPPORTED
+  case JBUF_SAVE_AND_PASS:
+    /* First pass of 2-pass quantization */
+    if (post->whole_image == NULL)
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    post->pub.post_process_data = post_process_prepass;
+    break;
+  case JBUF_CRANK_DEST:
+    /* Second pass of 2-pass quantization */
+    if (post->whole_image == NULL)
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    post->pub.post_process_data = post_process_2pass;
+    break;
+#endif /* QUANT_2PASS_SUPPORTED */
+  default:
+    ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+    break;
+  }
+  post->starting_row = post->next_row = 0;
+}
+
+
+/*
+ * Process some data in the one-pass (strip buffer) case.
+ * This is used for color precision reduction as well as one-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_1pass (j_decompress_ptr cinfo,
+        JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+        JDIMENSION in_row_groups_avail,
+        JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+        JDIMENSION out_rows_avail)
+{
+  my_post_ptr post = (my_post_ptr) cinfo->post;
+  JDIMENSION num_rows, max_rows;
+
+  /* Fill the buffer, but not more than what we can dump out in one go. */
+  /* Note we rely on the upsampler to detect bottom of image. */
+  max_rows = out_rows_avail - *out_row_ctr;
+  if (max_rows > post->strip_height)
+    max_rows = post->strip_height;
+  num_rows = 0;
+  (*cinfo->upsample->upsample) (cinfo,
+    input_buf, in_row_group_ctr, in_row_groups_avail,
+    post->buffer, &num_rows, max_rows);
+  /* Quantize and emit data. */
+  (*cinfo->cquantize->color_quantize) (cinfo,
+    post->buffer, output_buf + *out_row_ctr, (int) num_rows);
+  *out_row_ctr += num_rows;
+}
+
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+/*
+ * Process some data in the first pass of 2-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_prepass (j_decompress_ptr cinfo,
+          JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+          JDIMENSION in_row_groups_avail,
+          JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+          JDIMENSION out_rows_avail)
+{
+  my_post_ptr post = (my_post_ptr) cinfo->post;
+  JDIMENSION old_next_row, num_rows;
+  (void)output_buf;(void)out_rows_avail;
+
+  /* Reposition virtual buffer if at start of strip. */
+  if (post->next_row == 0) {
+    post->buffer = (*cinfo->mem->access_virt_sarray)
+  ((j_common_ptr) cinfo, post->whole_image,
+   post->starting_row, post->strip_height, TRUE);
+  }
+
+  /* Upsample some data (up to a strip height's worth). */
+  old_next_row = post->next_row;
+  (*cinfo->upsample->upsample) (cinfo,
+    input_buf, in_row_group_ctr, in_row_groups_avail,
+    post->buffer, &post->next_row, post->strip_height);
+
+  /* Allow quantizer to scan new data.  No data is emitted, */
+  /* but we advance out_row_ctr so outer loop can tell when we're done. */
+  if (post->next_row > old_next_row) {
+    num_rows = post->next_row - old_next_row;
+    (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
+           (JSAMPARRAY) NULL, (int) num_rows);
+    *out_row_ctr += num_rows;
+  }
+
+  /* Advance if we filled the strip. */
+  if (post->next_row >= post->strip_height) {
+    post->starting_row += post->strip_height;
+    post->next_row = 0;
+  }
+}
+
+
+/*
+ * Process some data in the second pass of 2-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_2pass (j_decompress_ptr cinfo,
+        JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+        JDIMENSION in_row_groups_avail,
+        JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+        JDIMENSION out_rows_avail)
+{
+  my_post_ptr post = (my_post_ptr) cinfo->post;
+  JDIMENSION num_rows, max_rows;
+  (void)input_buf;(void)in_row_group_ctr;(void)in_row_groups_avail;
+
+  /* Reposition virtual buffer if at start of strip. */
+  if (post->next_row == 0) {
+    post->buffer = (*cinfo->mem->access_virt_sarray)
+  ((j_common_ptr) cinfo, post->whole_image,
+   post->starting_row, post->strip_height, FALSE);
+  }
+
+  /* Determine number of rows to emit. */
+  num_rows = post->strip_height - post->next_row; /* available in strip */
+  max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
+  if (num_rows > max_rows)
+    num_rows = max_rows;
+  /* We have to check bottom of image here, can't depend on upsampler. */
+  max_rows = cinfo->output_height - post->starting_row;
+  if (num_rows > max_rows)
+    num_rows = max_rows;
+
+  /* Quantize and emit data. */
+  (*cinfo->cquantize->color_quantize) (cinfo,
+    post->buffer + post->next_row, output_buf + *out_row_ctr,
+    (int) num_rows);
+  *out_row_ctr += num_rows;
+
+  /* Advance if we filled the strip. */
+  post->next_row += num_rows;
+  if (post->next_row >= post->strip_height) {
+    post->starting_row += post->strip_height;
+    post->next_row = 0;
+  }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+
+
+/*
+ * Initialize postprocessing controller.
+ */
+
+GLOBAL(void)
+jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+  my_post_ptr post;
+
+  post = (my_post_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_post_controller));
+  cinfo->post = (struct jpeg_d_post_controller *) post;
+  post->pub.start_pass = start_pass_dpost;
+  post->whole_image = NULL;  /* flag for no virtual arrays */
+  post->buffer = NULL;    /* flag for no strip buffer */
+
+  /* Create the quantization buffer, if needed */
+  if (cinfo->quantize_colors) {
+    /* The buffer strip height is max_v_samp_factor, which is typically
+     * an efficient number of rows for upsampling to return.
+     * (In the presence of output rescaling, we might want to be smarter?)
+     */
+    post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
+    if (need_full_buffer) {
+      /* Two-pass color quantization: need full-image storage. */
+      /* We round up the number of rows to a multiple of the strip height. */
+#ifdef QUANT_2PASS_SUPPORTED
+      post->whole_image = (*cinfo->mem->request_virt_sarray)
+  ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+   cinfo->output_width * cinfo->out_color_components,
+   (JDIMENSION) jround_up((long) cinfo->output_height,
+        (long) post->strip_height),
+   post->strip_height);
+#else
+      ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif /* QUANT_2PASS_SUPPORTED */
+    } else {
+      /* One-pass color quantization: just make a strip buffer. */
+      post->buffer = (*cinfo->mem->alloc_sarray)
+  ((j_common_ptr) cinfo, JPOOL_IMAGE,
+   cinfo->output_width * cinfo->out_color_components,
+   post->strip_height);
+    }
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdpred.c b/Utilities/ITK/Utilities/itkjpeg/jdpred.c
new file mode 100644
index 0000000000000000000000000000000000000000..4704fc4f9c3491959c56b1a6fcfe873f35e5253b
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdpred.c
@@ -0,0 +1,258 @@
+/*
+ * jdpred.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains sample undifferencing (reconstruction) for lossless JPEG.
+ *
+ * In order to avoid paying the performance penalty of having to check the
+ * predictor being used and the row being processed for each call of the
+ * undifferencer, and to promote optimization, we have separate undifferencing
+ * functions for each case.
+ *
+ * We are able to avoid duplicating source code by implementing the predictors
+ * and undifferencers as macros.  Each of the undifferencing functions are
+ * simply wrappers around an UNDIFFERENCE macro with the appropriate PREDICTOR
+ * macro passed as an argument.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossls.h"    /* Private declarations for lossless codec */
+
+
+#ifdef D_LOSSLESS_SUPPORTED
+
+/* Predictor for the first column of the first row: 2^(P-Pt-1) */
+#define INITIAL_PREDICTORx  (1 << (cinfo->data_precision - cinfo->Al - 1))
+
+/* Predictor for the first column of the remaining rows: Rb */
+#define INITIAL_PREDICTOR2  GETJSAMPLE(prev_row[0])
+
+
+/*
+ * 1-Dimensional undifferencer routine.
+ *
+ * This macro implements the 1-D horizontal predictor (1).  INITIAL_PREDICTOR
+ * is used as the special case predictor for the first column, which must be
+ * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx.  The remaining samples
+ * use PREDICTOR1.
+ *
+ * The reconstructed sample is supposed to be calculated modulo 2^16, so we
+ * logically AND the result with 0xFFFF.
+*/
+
+#define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \
+  unsigned int xindex; \
+  int Ra; \
+ \
+  Ra = (diff_buf[0] + INITIAL_PREDICTOR) & 0xFFFF; \
+  undiff_buf[0] = Ra; \
+ \
+  for (xindex = 1; xindex < width; xindex++) { \
+    Ra = (diff_buf[xindex] + PREDICTOR1) & 0xFFFF; \
+    undiff_buf[xindex] = Ra; \
+  }
+
+/*
+ * 2-Dimensional undifferencer routine.
+ *
+ * This macro implements the 2-D horizontal predictors (#2-7).  PREDICTOR2 is
+ * used as the special case predictor for the first column.  The remaining
+ * samples use PREDICTOR, which is a function of Ra, Rb, Rc.
+ *
+ * Because prev_row and output_buf may point to the same storage area (in an
+ * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc
+ * before writing the current reconstructed sample value into output_buf.
+ *
+ * The reconstructed sample is supposed to be calculated modulo 2^16, so we
+ * logically AND the result with 0xFFFF.
+ */
+
+#define UNDIFFERENCE_2D(PREDICTOR) \
+  unsigned int xindex; \
+  int Ra, Rb, Rc; \
+ \
+  Rb = GETJSAMPLE(prev_row[0]); \
+  Ra = (diff_buf[0] + PREDICTOR2) & 0xFFFF; \
+  undiff_buf[0] = Ra; \
+ \
+  for (xindex = 1; xindex < width; xindex++) { \
+    Rc = Rb; \
+    Rb = GETJSAMPLE(prev_row[xindex]); \
+    Ra = (diff_buf[xindex] + PREDICTOR) & 0xFFFF; \
+    undiff_buf[xindex] = Ra; \
+  }
+
+
+/*
+ * Undifferencers for the all rows but the first in a scan or restart interval.
+ * The first sample in the row is undifferenced using the vertical
+ * predictor (2).  The rest of the samples are undifferenced using the
+ * predictor specified in the scan header.
+ */
+
+METHODDEF(void)
+jpeg_undifference1(j_decompress_ptr cinfo, int comp_index,
+       JDIFFROW diff_buf, JDIFFROW prev_row,
+       JDIFFROW undiff_buf, JDIMENSION width)
+{
+  UNDIFFERENCE_1D(INITIAL_PREDICTOR2);
+  (void)cinfo;(void)comp_index;(void)diff_buf;(void)prev_row;(void)undiff_buf;(void)width;
+}
+
+METHODDEF(void)
+jpeg_undifference2(j_decompress_ptr cinfo, int comp_index,
+       JDIFFROW diff_buf, JDIFFROW prev_row,
+       JDIFFROW undiff_buf, JDIMENSION width)
+{
+  UNDIFFERENCE_2D(PREDICTOR2);
+  (void)cinfo;(void)comp_index;(void)diff_buf;(void)prev_row;(void)undiff_buf;(void)width;
+}
+
+METHODDEF(void)
+jpeg_undifference3(j_decompress_ptr cinfo, int comp_index,
+       JDIFFROW diff_buf, JDIFFROW prev_row,
+       JDIFFROW undiff_buf, JDIMENSION width)
+{
+  UNDIFFERENCE_2D(PREDICTOR3);
+  (void)cinfo;(void)comp_index;(void)diff_buf;(void)prev_row;(void)undiff_buf;(void)width;
+}
+
+METHODDEF(void)
+jpeg_undifference4(j_decompress_ptr cinfo, int comp_index,
+       JDIFFROW diff_buf, JDIFFROW prev_row,
+       JDIFFROW undiff_buf, JDIMENSION width)
+{
+  UNDIFFERENCE_2D(PREDICTOR4);
+  (void)cinfo;(void)comp_index;(void)diff_buf;(void)prev_row;(void)undiff_buf;(void)width;
+}
+
+METHODDEF(void)
+jpeg_undifference5(j_decompress_ptr cinfo, int comp_index,
+       JDIFFROW diff_buf, JDIFFROW prev_row,
+       JDIFFROW undiff_buf, JDIMENSION width)
+{
+  SHIFT_TEMPS
+  UNDIFFERENCE_2D(PREDICTOR5);
+  (void)cinfo;(void)comp_index;(void)diff_buf;(void)prev_row;(void)undiff_buf;(void)width;
+}
+
+METHODDEF(void)
+jpeg_undifference6(j_decompress_ptr cinfo, int comp_index,
+       JDIFFROW diff_buf, JDIFFROW prev_row,
+       JDIFFROW undiff_buf, JDIMENSION width)
+{
+  SHIFT_TEMPS
+  UNDIFFERENCE_2D(PREDICTOR6);
+  (void)cinfo;(void)comp_index;(void)diff_buf;(void)prev_row;(void)undiff_buf;(void)width;
+}
+
+METHODDEF(void)
+jpeg_undifference7(j_decompress_ptr cinfo, int comp_index,
+       JDIFFROW diff_buf, JDIFFROW prev_row,
+       JDIFFROW undiff_buf, JDIMENSION width)
+{
+  SHIFT_TEMPS
+  UNDIFFERENCE_2D(PREDICTOR7);
+  (void)cinfo;(void)comp_index;(void)diff_buf;(void)prev_row;(void)undiff_buf;(void)width;
+}
+
+
+/*
+ * Undifferencer for the first row in a scan or restart interval.  The first
+ * sample in the row is undifferenced using the special predictor constant
+ * x=2^(P-Pt-1).  The rest of the samples are undifferenced using the
+ * 1-D horizontal predictor (1).
+ */
+
+METHODDEF(void)
+jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index,
+          JDIFFROW diff_buf, JDIFFROW prev_row,
+          JDIFFROW undiff_buf, JDIMENSION width)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+
+  UNDIFFERENCE_1D(INITIAL_PREDICTORx);
+  (void)prev_row;
+
+  /*
+   * Now that we have undifferenced the first row, we want to use the
+   * undifferencer which corresponds to the predictor specified in the
+   * scan header.
+   */
+  switch (cinfo->Ss) {
+  case 1:
+    losslsd->predict_undifference[comp_index] = jpeg_undifference1;
+    break;
+  case 2:
+    losslsd->predict_undifference[comp_index] = jpeg_undifference2;
+    break;
+  case 3:
+    losslsd->predict_undifference[comp_index] = jpeg_undifference3;
+    break;
+  case 4:
+    losslsd->predict_undifference[comp_index] = jpeg_undifference4;
+    break;
+  case 5:
+    losslsd->predict_undifference[comp_index] = jpeg_undifference5;
+    break;
+  case 6:
+    losslsd->predict_undifference[comp_index] = jpeg_undifference6;
+    break;
+  case 7:
+    losslsd->predict_undifference[comp_index] = jpeg_undifference7;
+    break;
+  }
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+predict_start_pass (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  int ci;
+
+  /* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG.
+   *
+   * Ss is the predictor selection value (psv).  Legal values for sequential
+   * lossless JPEG are: 1 <= psv <= 7.
+   *
+   * Se and Ah are not used and should be zero.
+   *
+   * Al specifies the point transform (Pt).  Legal values are: 0 <= Pt <= 15.
+   */
+  if (cinfo->Ss < 1 || cinfo->Ss > 7 ||
+      cinfo->Se != 0 || cinfo->Ah != 0 ||
+      cinfo->Al > 15)        /* need not check for < 0 */
+    ERREXIT4(cinfo, JERR_BAD_LOSSLESS,
+       cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
+
+  /* Set undifference functions to first row function */
+  for (ci = 0; ci < cinfo->num_components; ci++)
+    losslsd->predict_undifference[ci] = jpeg_undifference_first_row;
+}
+
+
+/*
+ * Module initialization routine for the undifferencer.
+ */
+
+GLOBAL(void)
+jinit_undifferencer (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+
+  losslsd->predict_start_pass = predict_start_pass;
+  losslsd->predict_process_restart = predict_start_pass;
+}
+
+#endif /* D_LOSSLESS_SUPPORTED */
+
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdsample.c b/Utilities/ITK/Utilities/itkjpeg/jdsample.c
new file mode 100644
index 0000000000000000000000000000000000000000..a36283e29c293d8e218e9f99a1872e4ac57e9581
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdsample.c
@@ -0,0 +1,483 @@
+/*
+ * jdsample.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains upsampling routines.
+ *
+ * Upsampling input data is counted in "row groups".  A row group
+ * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit)
+ * sample rows of each component.  Upsampling will normally produce
+ * max_v_samp_factor pixel rows from each row group (but this could vary
+ * if the upsampler is applying a scale factor of its own).
+ *
+ * An excellent reference for image resampling is
+ *   Digital Image Warping, George Wolberg, 1990.
+ *   Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Pointer to routine to upsample a single component */
+typedef JMETHOD(void, upsample1_ptr,
+    (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+     JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
+
+/* Private subobject */
+
+typedef struct {
+  struct jpeg_upsampler pub;  /* public fields */
+
+  /* Color conversion buffer.  When using separate upsampling and color
+   * conversion steps, this buffer holds one upsampled row group until it
+   * has been color converted and output.
+   * Note: we do not allocate any storage for component(s) which are full-size,
+   * ie do not need rescaling.  The corresponding entry of color_buf[] is
+   * simply set to point to the input data array, thereby avoiding copying.
+   */
+  JSAMPARRAY color_buf[MAX_COMPONENTS];
+
+  /* Per-component upsampling method pointers */
+  upsample1_ptr methods[MAX_COMPONENTS];
+
+  int next_row_out;    /* counts rows emitted from color_buf */
+  JDIMENSION rows_to_go;  /* counts rows remaining in image */
+
+  /* Height of an input row group for each component. */
+  int rowgroup_height[MAX_COMPONENTS];
+
+  /* These arrays save pixel expansion factors so that int_expand need not
+   * recompute them each time.  They are unused for other upsampling methods.
+   */
+  UINT8 h_expand[MAX_COMPONENTS];
+  UINT8 v_expand[MAX_COMPONENTS];
+} my_upsampler;
+
+typedef my_upsampler * my_upsample_ptr;
+
+
+/*
+ * Initialize for an upsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_upsample (j_decompress_ptr cinfo)
+{
+  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+  /* Mark the conversion buffer empty */
+  upsample->next_row_out = cinfo->max_v_samp_factor;
+  /* Initialize total-height counter for detecting bottom of image */
+  upsample->rows_to_go = cinfo->output_height;
+}
+
+
+/*
+ * Control routine to do upsampling (and color conversion).
+ *
+ * In this version we upsample each component independently.
+ * We upsample one row group into the conversion buffer, then apply
+ * color conversion a row at a time.
+ */
+
+METHODDEF(void)
+sep_upsample (j_decompress_ptr cinfo,
+        JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+        JDIMENSION in_row_groups_avail,
+        JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+        JDIMENSION out_rows_avail)
+{
+  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+  int ci;
+  jpeg_component_info * compptr;
+  JDIMENSION num_rows;
+  (void)in_row_groups_avail;
+
+  /* Fill the conversion buffer, if it's empty */
+  if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
+    for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+   ci++, compptr++) {
+      /* Invoke per-component upsample method.  Notice we pass a POINTER
+       * to color_buf[ci], so that fullsize_upsample can change it.
+       */
+      (*upsample->methods[ci]) (cinfo, compptr,
+  input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
+  upsample->color_buf + ci);
+    }
+    upsample->next_row_out = 0;
+  }
+
+  /* Color-convert and emit rows */
+
+  /* How many we have in the buffer: */
+  num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
+  /* Not more than the distance to the end of the image.  Need this test
+   * in case the image height is not a multiple of max_v_samp_factor:
+   */
+  if (num_rows > upsample->rows_to_go) 
+    num_rows = upsample->rows_to_go;
+  /* And not more than what the client can accept: */
+  out_rows_avail -= *out_row_ctr;
+  if (num_rows > out_rows_avail)
+    num_rows = out_rows_avail;
+
+  (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
+             (JDIMENSION) upsample->next_row_out,
+             output_buf + *out_row_ctr,
+             (int) num_rows);
+
+  /* Adjust counts */
+  *out_row_ctr += num_rows;
+  upsample->rows_to_go -= num_rows;
+  upsample->next_row_out += num_rows;
+  /* When the buffer is emptied, declare this input row group consumed */
+  if (upsample->next_row_out >= cinfo->max_v_samp_factor)
+    (*in_row_group_ctr)++;
+}
+
+
+/*
+ * These are the routines invoked by sep_upsample to upsample pixel values
+ * of a single component.  One row group is processed per call.
+ */
+
+
+/*
+ * For full-size components, we just make color_buf[ci] point at the
+ * input buffer, and thus avoid copying any data.  Note that this is
+ * safe only because sep_upsample doesn't declare the input row group
+ * "consumed" until we are done color converting and emitting it.
+ */
+
+METHODDEF(void)
+fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+       JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+  (void)cinfo;(void)compptr;
+  *output_data_ptr = input_data;
+}
+
+
+/*
+ * This is a no-op version used for "uninteresting" components.
+ * These components will not be referenced by color conversion.
+ */
+
+METHODDEF(void)
+noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+         JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+  (void)cinfo;(void)compptr;(void)input_data;
+  *output_data_ptr = NULL;  /* safety check */
+}
+
+
+/*
+ * This version handles any integral sampling ratios.
+ * This is not used for typical JPEG files, so it need not be fast.
+ * Nor, for that matter, is it particularly accurate: the algorithm is
+ * simple replication of the input pixel onto the corresponding output
+ * pixels.  The hi-falutin sampling literature refers to this as a
+ * "box filter".  A box filter tends to introduce visible artifacts,
+ * so if you are actually going to use 3:1 or 4:1 sampling ratios
+ * you would be well advised to improve this code.
+ */
+
+METHODDEF(void)
+int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+        JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+  my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+  JSAMPARRAY output_data = *output_data_ptr;
+  register JSAMPROW inptr, outptr;
+  register JSAMPLE invalue;
+  register int h;
+  JSAMPROW outend;
+  int h_expand, v_expand;
+  int inrow, outrow;
+
+  h_expand = upsample->h_expand[compptr->component_index];
+  v_expand = upsample->v_expand[compptr->component_index];
+
+  inrow = outrow = 0;
+  while (outrow < cinfo->max_v_samp_factor) {
+    /* Generate one output row with proper horizontal expansion */
+    inptr = input_data[inrow];
+    outptr = output_data[outrow];
+    outend = outptr + cinfo->output_width;
+    while (outptr < outend) {
+      invalue = *inptr++;  /* don't need GETJSAMPLE() here */
+      for (h = h_expand; h > 0; h--) {
+  *outptr++ = invalue;
+      }
+    }
+    /* Generate any additional output rows by duplicating the first one */
+    if (v_expand > 1) {
+      jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
+      v_expand-1, cinfo->output_width);
+    }
+    inrow++;
+    outrow += v_expand;
+  }
+}
+
+
+/*
+ * Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
+ * It's still a box filter.
+ */
+
+METHODDEF(void)
+h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+         JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+  JSAMPARRAY output_data = *output_data_ptr;
+  register JSAMPROW inptr, outptr;
+  register JSAMPLE invalue;
+  JSAMPROW outend;
+  int inrow;
+  (void)compptr;
+
+  for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
+    inptr = input_data[inrow];
+    outptr = output_data[inrow];
+    outend = outptr + cinfo->output_width;
+    while (outptr < outend) {
+      invalue = *inptr++;  /* don't need GETJSAMPLE() here */
+      *outptr++ = invalue;
+      *outptr++ = invalue;
+    }
+  }
+}
+
+
+/*
+ * Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
+ * It's still a box filter.
+ */
+
+METHODDEF(void)
+h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+         JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+  JSAMPARRAY output_data = *output_data_ptr;
+  register JSAMPROW inptr, outptr;
+  register JSAMPLE invalue;
+  JSAMPROW outend;
+  int inrow, outrow;
+  (void)compptr;
+
+  inrow = outrow = 0;
+  while (outrow < cinfo->max_v_samp_factor) {
+    inptr = input_data[inrow];
+    outptr = output_data[outrow];
+    outend = outptr + cinfo->output_width;
+    while (outptr < outend) {
+      invalue = *inptr++;  /* don't need GETJSAMPLE() here */
+      *outptr++ = invalue;
+      *outptr++ = invalue;
+    }
+    jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
+          1, cinfo->output_width);
+    inrow++;
+    outrow += 2;
+  }
+}
+
+
+/*
+ * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
+ *
+ * The upsampling algorithm is linear interpolation between pixel centers,
+ * also known as a "triangle filter".  This is a good compromise between
+ * speed and visual quality.  The centers of the output pixels are 1/4 and 3/4
+ * of the way between input pixel centers.
+ *
+ * A note about the "bias" calculations: when rounding fractional values to
+ * integer, we do not want to always round 0.5 up to the next integer.
+ * If we did that, we'd introduce a noticeable bias towards larger values.
+ * Instead, this code is arranged so that 0.5 will be rounded up or down at
+ * alternate pixel locations (a simple ordered dither pattern).
+ */
+
+METHODDEF(void)
+h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+         JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+  JSAMPARRAY output_data = *output_data_ptr;
+  register JSAMPROW inptr, outptr;
+  register int invalue;
+  register JDIMENSION colctr;
+  int inrow;
+
+  for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
+    inptr = input_data[inrow];
+    outptr = output_data[inrow];
+    /* Special case for first column */
+    invalue = GETJSAMPLE(*inptr++);
+    *outptr++ = (JSAMPLE) invalue;
+    *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
+
+    for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
+      /* General case: 3/4 * nearer pixel + 1/4 * further pixel */
+      invalue = GETJSAMPLE(*inptr++) * 3;
+      *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
+      *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
+    }
+
+    /* Special case for last column */
+    invalue = GETJSAMPLE(*inptr);
+    *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
+    *outptr++ = (JSAMPLE) invalue;
+  }
+}
+
+
+/*
+ * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
+ * Again a triangle filter; see comments for h2v1 case, above.
+ *
+ * It is OK for us to reference the adjacent input rows because we demanded
+ * context from the main buffer controller (see initialization code).
+ */
+
+METHODDEF(void)
+h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+         JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+  JSAMPARRAY output_data = *output_data_ptr;
+  register JSAMPROW inptr0, inptr1, outptr;
+#if BITS_IN_JSAMPLE == 8
+  register int thiscolsum, lastcolsum, nextcolsum;
+#else
+  register INT32 thiscolsum, lastcolsum, nextcolsum;
+#endif
+  register JDIMENSION colctr;
+  int inrow, outrow, v;
+
+  inrow = outrow = 0;
+  while (outrow < cinfo->max_v_samp_factor) {
+    for (v = 0; v < 2; v++) {
+      /* inptr0 points to nearest input row, inptr1 points to next nearest */
+      inptr0 = input_data[inrow];
+      if (v == 0)    /* next nearest is row above */
+  inptr1 = input_data[inrow-1];
+      else      /* next nearest is row below */
+  inptr1 = input_data[inrow+1];
+      outptr = output_data[outrow++];
+
+      /* Special case for first column */
+      thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
+      nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
+      *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
+      *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
+      lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+
+      for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
+  /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
+  /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
+  nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
+  *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
+  *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
+  lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+      }
+
+      /* Special case for last column */
+      *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
+      *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
+    }
+    inrow++;
+  }
+}
+
+
+/*
+ * Module initialization routine for upsampling.
+ */
+
+GLOBAL(void)
+jinit_upsampler (j_decompress_ptr cinfo)
+{
+  my_upsample_ptr upsample;
+  int ci;
+  jpeg_component_info * compptr;
+  boolean need_buffer, do_fancy;
+  int h_in_group, v_in_group, h_out_group, v_out_group;
+
+  upsample = (my_upsample_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_upsampler));
+  cinfo->upsample = (struct jpeg_upsampler *) upsample;
+  upsample->pub.start_pass = start_pass_upsample;
+  upsample->pub.upsample = sep_upsample;
+  upsample->pub.need_context_rows = FALSE; /* until we find out differently */
+
+  if (cinfo->CCIR601_sampling)  /* this isn't supported */
+    ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
+
+  /* jdmainct.c doesn't support context rows when min_codec_data_unit = 1,
+   * so don't ask for it.
+   */
+  do_fancy = cinfo->do_fancy_upsampling && cinfo->min_codec_data_unit > 1;
+
+  /* Verify we can handle the sampling factors, select per-component methods,
+   * and create storage as needed.
+   */
+  for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+       ci++, compptr++) {
+    /* Compute size of an "input group" after IDCT scaling.  This many samples
+     * are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
+     */
+    h_in_group = (compptr->h_samp_factor * compptr->codec_data_unit) /
+     cinfo->min_codec_data_unit;
+    v_in_group = (compptr->v_samp_factor * compptr->codec_data_unit) /
+     cinfo->min_codec_data_unit;
+    h_out_group = cinfo->max_h_samp_factor;
+    v_out_group = cinfo->max_v_samp_factor;
+    upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
+    need_buffer = TRUE;
+    if (! compptr->component_needed) {
+      /* Don't bother to upsample an uninteresting component. */
+      upsample->methods[ci] = noop_upsample;
+      need_buffer = FALSE;
+    } else if (h_in_group == h_out_group && v_in_group == v_out_group) {
+      /* Fullsize components can be processed without any work. */
+      upsample->methods[ci] = fullsize_upsample;
+      need_buffer = FALSE;
+    } else if (h_in_group * 2 == h_out_group &&
+         v_in_group == v_out_group) {
+      /* Special cases for 2h1v upsampling */
+      if (do_fancy && compptr->downsampled_width > 2)
+  upsample->methods[ci] = h2v1_fancy_upsample;
+      else
+  upsample->methods[ci] = h2v1_upsample;
+    } else if (h_in_group * 2 == h_out_group &&
+         v_in_group * 2 == v_out_group) {
+      /* Special cases for 2h2v upsampling */
+      if (do_fancy && compptr->downsampled_width > 2) {
+  upsample->methods[ci] = h2v2_fancy_upsample;
+  upsample->pub.need_context_rows = TRUE;
+      } else
+  upsample->methods[ci] = h2v2_upsample;
+    } else if ((h_out_group % h_in_group) == 0 &&
+         (v_out_group % v_in_group) == 0) {
+      /* Generic integral-factors upsampling method */
+      upsample->methods[ci] = int_upsample;
+      upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
+      upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
+    } else
+      ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
+    if (need_buffer) {
+      upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
+  ((j_common_ptr) cinfo, JPOOL_IMAGE,
+   (JDIMENSION) jround_up((long) cinfo->output_width,
+        (long) cinfo->max_h_samp_factor),
+   (JDIMENSION) cinfo->max_v_samp_factor);
+    }
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdscale.c b/Utilities/ITK/Utilities/itkjpeg/jdscale.c
new file mode 100644
index 0000000000000000000000000000000000000000..9cdd9b7260ae5a360757647bbccf354ca81b7129
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdscale.c
@@ -0,0 +1,120 @@
+/*
+ * jdscale.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains sample scaling for lossless JPEG.  This is a
+ * combination of upscaling the undifferenced sample by 2^Pt and downscaling
+ * the sample to fit into JSAMPLE.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossls.h"    /* Private declarations for lossless codec */
+
+
+#ifdef D_LOSSLESS_SUPPORTED
+
+/*
+ * Private scaler object for lossless decoding.
+ */
+
+typedef struct {
+  int scale_factor;
+} scaler;
+
+typedef scaler * scaler_ptr;
+
+
+/*
+ * Scalers for packing sample differences into JSAMPLEs.
+ */
+
+METHODDEF(void)
+simple_upscale(j_decompress_ptr cinfo,
+         JDIFFROW diff_buf, JSAMPROW output_buf,
+         JDIMENSION width)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private;
+  int scale_factor = scaler->scale_factor;
+  unsigned int xindex;
+
+  for (xindex = 0; xindex < width; xindex++)
+    output_buf[xindex] = (JSAMPLE) (diff_buf[xindex] << scale_factor);
+}
+
+METHODDEF(void)
+simple_downscale(j_decompress_ptr cinfo,
+     JDIFFROW diff_buf, JSAMPROW output_buf,
+     JDIMENSION width)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private;
+  int scale_factor = scaler->scale_factor;
+  unsigned int xindex;
+  SHIFT_TEMPS
+
+  for (xindex = 0; xindex < width; xindex++)
+    output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(diff_buf[xindex], scale_factor);
+}
+
+METHODDEF(void)
+noscale(j_decompress_ptr cinfo,
+  JDIFFROW diff_buf, JSAMPROW output_buf,
+  JDIMENSION width)
+{
+  unsigned int xindex;
+  (void)cinfo;
+
+  for (xindex = 0; xindex < width; xindex++)
+    output_buf[xindex] = (JSAMPLE) diff_buf[xindex];
+}
+
+
+METHODDEF(void)
+scaler_start_pass (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private;
+  int downscale;
+
+  /*
+   * Downscale by the difference in the input vs. output precision.  If the
+   * output precision >= input precision, then do not downscale.
+   */
+  downscale = BITS_IN_JSAMPLE < cinfo->data_precision ?
+    cinfo->data_precision - BITS_IN_JSAMPLE : 0;
+
+  scaler->scale_factor = cinfo->Al - downscale;
+
+  /* Set scaler functions based on scale_factor (positive = left shift) */
+  if (scaler->scale_factor > 0)
+    losslsd->scaler_scale = simple_upscale;
+  else if (scaler->scale_factor < 0) {
+    scaler->scale_factor = -scaler->scale_factor;
+    losslsd->scaler_scale = simple_downscale;
+  }
+  else
+    losslsd->scaler_scale = noscale;
+}
+
+
+GLOBAL(void)
+jinit_d_scaler (j_decompress_ptr cinfo)
+{
+  j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+  scaler_ptr scaler;
+
+  scaler = (scaler_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(scaler));
+  losslsd->scaler_private = (void *) scaler;
+  losslsd->scaler_start_pass = scaler_start_pass;
+}
+
+#endif /* D_LOSSLESS_SUPPORTED */
+
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdshuff.c b/Utilities/ITK/Utilities/itkjpeg/jdshuff.c
new file mode 100644
index 0000000000000000000000000000000000000000..326220c478714e9ef0b66e072285073bd5a80c67
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdshuff.c
@@ -0,0 +1,360 @@
+/*
+ * jdshuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines for sequential JPEG.
+ *
+ * Much of the complexity here has to do with supporting input suspension.
+ * If the data source module demands suspension, we want to be able to back
+ * up to the start of the current MCU.  To do this, we copy state variables
+ * into local working storage, and update them back to the permanent
+ * storage only upon successful completion of an MCU.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"    /* Private declarations for lossy codec */
+#include "jdhuff.h"    /* Declarations shared with jd*huff.c */
+
+
+/*
+ * Private entropy decoder object for Huffman decoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+  int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment.  You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src)  ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src)  \
+  ((dest).last_dc_val[0] = (src).last_dc_val[0], \
+   (dest).last_dc_val[1] = (src).last_dc_val[1], \
+   (dest).last_dc_val[2] = (src).last_dc_val[2], \
+   (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+  huffd_common_fields;    /* Fields shared with other entropy decoders */
+
+  /* These fields are loaded into local variables at start of each MCU.
+   * In case of suspension, we exit WITHOUT updating them.
+   */
+  savable_state saved;    /* Other state at start of MCU */
+
+  /* These fields are NOT loaded into local working state. */
+  unsigned int restarts_to_go;  /* MCUs left in this restart interval */
+
+  /* Pointers to derived tables (these workspaces have image lifespan) */
+  d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
+  d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
+
+  /* Precalculated info set up by start_pass for use in decode_mcu: */
+
+  /* Pointers to derived tables to be used for each block within an MCU */
+  d_derived_tbl * dc_cur_tbls[D_MAX_DATA_UNITS_IN_MCU];
+  d_derived_tbl * ac_cur_tbls[D_MAX_DATA_UNITS_IN_MCU];
+  /* Whether we care about the DC and AC coefficient values for each block */
+  boolean dc_needed[D_MAX_DATA_UNITS_IN_MCU];
+  boolean ac_needed[D_MAX_DATA_UNITS_IN_MCU];
+} shuff_entropy_decoder;
+
+typedef shuff_entropy_decoder * shuff_entropy_ptr;
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass_huff_decoder (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private;
+  int ci, blkn, dctbl, actbl;
+  jpeg_component_info * compptr;
+
+  /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
+   * This ought to be an error condition, but we make it a warning because
+   * there are some baseline files out there with all zeroes in these bytes.
+   */
+  if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
+      cinfo->Ah != 0 || cinfo->Al != 0)
+    WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
+
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+    compptr = cinfo->cur_comp_info[ci];
+    dctbl = compptr->dc_tbl_no;
+    actbl = compptr->ac_tbl_no;
+    /* Compute derived values for Huffman tables */
+    /* We may do this more than once for a table, but it's not expensive */
+    jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
+          & entropy->dc_derived_tbls[dctbl]);
+    jpeg_make_d_derived_tbl(cinfo, FALSE, actbl,
+          & entropy->ac_derived_tbls[actbl]);
+    /* Initialize DC predictions to 0 */
+    entropy->saved.last_dc_val[ci] = 0;
+  }
+
+  /* Precalculate decoding info for each block in an MCU of this scan */
+  for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+    ci = cinfo->MCU_membership[blkn];
+    compptr = cinfo->cur_comp_info[ci];
+    /* Precalculate which table to use for each block */
+    entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no];
+    entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no];
+    /* Decide whether we really care about the coefficient values */
+    if (compptr->component_needed) {
+      entropy->dc_needed[blkn] = TRUE;
+      /* we don't need the ACs if producing a 1/8th-size image */
+      entropy->ac_needed[blkn] = (compptr->codec_data_unit > 1);
+    } else {
+      entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE;
+    }
+  }
+
+  /* Initialize bitread state variables */
+  entropy->bitstate.bits_left = 0;
+  entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+  entropy->insufficient_data = FALSE;
+
+  /* Initialize restart counter */
+  entropy->restarts_to_go = cinfo->restart_interval;
+}
+
+
+/*
+ * Figure F.12: extend sign bit.
+ * On some machines, a shift and add will be faster than a table lookup.
+ */
+
+#ifdef AVOID_TABLES
+
+#define HUFF_EXTEND(x,s)  ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
+
+#else
+
+#define HUFF_EXTEND(x,s)  ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+
+static const int extend_test[16] =   /* entry n is 2**(n-1) */
+  { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+    0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+
+static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
+  { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
+    ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
+    ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
+    ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+
+#endif /* AVOID_TABLES */
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ * Returns FALSE if must suspend.
+ */
+
+LOCAL(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private;
+  int ci;
+
+  /* Throw away any unused bits remaining in bit buffer; */
+  /* include any full bytes in next_marker's count of discarded bytes */
+  cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
+  entropy->bitstate.bits_left = 0;
+
+  /* Advance past the RSTn marker */
+  if (! (*cinfo->marker->read_restart_marker) (cinfo))
+    return FALSE;
+
+  /* Re-initialize DC predictions to 0 */
+  for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+    entropy->saved.last_dc_val[ci] = 0;
+
+  /* Reset restart counter */
+  entropy->restarts_to_go = cinfo->restart_interval;
+
+  /* Reset out-of-data flag, unless read_restart_marker left us smack up
+   * against a marker.  In that case we will end up treating the next data
+   * segment as empty, and we can avoid producing bogus output pixels by
+   * leaving the flag set.
+   */
+  if (cinfo->unread_marker == 0)
+    entropy->insufficient_data = FALSE;
+
+  return TRUE;
+}
+
+
+/*
+ * Decode and return one MCU's worth of Huffman-compressed coefficients.
+ * The coefficients are reordered from zigzag order into natural array order,
+ * but are not dequantized.
+ *
+ * The i'th block of the MCU is stored into the block pointed to by
+ * MCU_data[i].  WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
+ * (Wholesale zeroing is usually a little faster than retail...)
+ *
+ * Returns FALSE if data source requested suspension.  In that case no
+ * changes have been made to permanent state.  (Exception: some output
+ * coefficients may already have been assigned.  This is harmless for
+ * this module, since we'll just re-assign them on the next call.)
+ */
+
+METHODDEF(boolean)
+decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private;
+  int blkn;
+  BITREAD_STATE_VARS;
+  savable_state state;
+
+  /* Process restart marker if needed; may have to suspend */
+  if (cinfo->restart_interval) {
+    if (entropy->restarts_to_go == 0)
+      if (! process_restart(cinfo))
+  return FALSE;
+  }
+
+  /* If we've run out of data, just leave the MCU set to zeroes.
+   * This way, we return uniform gray for the remainder of the segment.
+   */
+  if (! entropy->insufficient_data) {
+
+    /* Load up working state */
+    BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+    ASSIGN_STATE(state, entropy->saved);
+
+    /* Outer loop handles each block in the MCU */
+
+    for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+      JBLOCKROW block = MCU_data[blkn];
+      d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
+      d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
+      register int s, k, r;
+
+      /* Decode a single block's worth of coefficients */
+
+      /* Section F.2.2.1: decode the DC coefficient difference */
+      HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
+      if (s) {
+  CHECK_BIT_BUFFER(br_state, s, return FALSE);
+  r = GET_BITS(s);
+  s = HUFF_EXTEND(r, s);
+      }
+
+      if (entropy->dc_needed[blkn]) {
+  /* Convert DC difference to actual value, update last_dc_val */
+  int ci = cinfo->MCU_membership[blkn];
+  s += state.last_dc_val[ci];
+  state.last_dc_val[ci] = s;
+  /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
+  (*block)[0] = (JCOEF) s;
+      }
+
+      if (entropy->ac_needed[blkn]) {
+
+  /* Section F.2.2.2: decode the AC coefficients */
+  /* Since zeroes are skipped, output area must be cleared beforehand */
+  for (k = 1; k < DCTSIZE2; k++) {
+    HUFF_DECODE(s, br_state, actbl, return FALSE, label2);
+      
+    r = s >> 4;
+    s &= 15;
+      
+    if (s) {
+      k += r;
+      CHECK_BIT_BUFFER(br_state, s, return FALSE);
+      r = GET_BITS(s);
+      s = HUFF_EXTEND(r, s);
+      /* Output coefficient in natural (dezigzagged) order.
+       * Note: the extra entries in jpeg_natural_order[] will save us
+       * if k >= DCTSIZE2, which could happen if the data is corrupted.
+       */
+      (*block)[jpeg_natural_order[k]] = (JCOEF) s;
+    } else {
+      if (r != 15)
+        break;
+      k += 15;
+    }
+  }
+
+      } else {
+
+  /* Section F.2.2.2: decode the AC coefficients */
+  /* In this path we just discard the values */
+  for (k = 1; k < DCTSIZE2; k++) {
+    HUFF_DECODE(s, br_state, actbl, return FALSE, label3);
+      
+    r = s >> 4;
+    s &= 15;
+      
+    if (s) {
+      k += r;
+      CHECK_BIT_BUFFER(br_state, s, return FALSE);
+      DROP_BITS(s);
+    } else {
+      if (r != 15)
+        break;
+      k += 15;
+    }
+  }
+
+      }
+    }
+
+    /* Completed MCU, so update state */
+    BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+    ASSIGN_STATE(entropy->saved, state);
+  }
+
+  /* Account for restart interval (no-op if not using restarts) */
+  entropy->restarts_to_go--;
+
+  return TRUE;
+}
+
+
+/*
+ * Module initialization routine for Huffman entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_shuff_decoder (j_decompress_ptr cinfo)
+{
+  j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+  shuff_entropy_ptr entropy;
+  int i;
+
+  entropy = (shuff_entropy_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(shuff_entropy_decoder));
+  lossyd->entropy_private = (void *) entropy;
+  lossyd->entropy_start_pass = start_pass_huff_decoder;
+  lossyd->entropy_decode_mcu = decode_mcu;
+
+  /* Mark tables unallocated */
+  for (i = 0; i < NUM_HUFF_TBLS; i++) {
+    entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jdtrans.c b/Utilities/ITK/Utilities/itkjpeg/jdtrans.c
new file mode 100644
index 0000000000000000000000000000000000000000..af35263c67a40c75caaf4c95460521626c9cffbb
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jdtrans.c
@@ -0,0 +1,138 @@
+/*
+ * jdtrans.c
+ *
+ * Copyright (C) 1995-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains library routines for transcoding decompression,
+ * that is, reading raw DCT coefficient arrays from an input JPEG file.
+ * The routines in jdapimin.c will also be needed by a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jlossy.h"
+
+
+/* Forward declarations */
+LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Read the coefficient arrays from a JPEG file.
+ * jpeg_read_header must be completed before calling this.
+ *
+ * The entire image is read into a set of virtual coefficient-block arrays,
+ * one per component.  The return value is a pointer to the array of
+ * virtual-array descriptors.  These can be manipulated directly via the
+ * JPEG memory manager, or handed off to jpeg_write_coefficients().
+ * To release the memory occupied by the virtual arrays, call
+ * jpeg_finish_decompress() when done with the data.
+ *
+ * An alternative usage is to simply obtain access to the coefficient arrays
+ * during a buffered-image-mode decompression operation.  This is allowed
+ * after any jpeg_finish_output() call.  The arrays can be accessed until
+ * jpeg_finish_decompress() is called.  (Note that any call to the library
+ * may reposition the arrays, so don't rely on access_virt_barray() results
+ * to stay valid across library calls.)
+ *
+ * Returns NULL if suspended.  This case need be checked only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(jvirt_barray_ptr *)
+jpeg_read_coefficients (j_decompress_ptr cinfo)
+{
+  /* j_lossy_d_ptr decomp; */
+
+  /* Can't read coefficients from lossless streams */
+  if (cinfo->process == JPROC_LOSSLESS) {
+    ERREXIT(cinfo, JERR_CANT_TRANSCODE);
+    return NULL;
+  }
+
+  if (cinfo->global_state == DSTATE_READY) {
+    /* First call: initialize active modules */
+    transdecode_master_selection(cinfo);
+    cinfo->global_state = DSTATE_RDCOEFS;
+  }
+  if (cinfo->global_state == DSTATE_RDCOEFS) {
+    /* Absorb whole file into the coef buffer */
+    for (;;) {
+      int retcode;
+      /* Call progress monitor hook if present */
+      if (cinfo->progress != NULL)
+  (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+      /* Absorb some more input */
+      retcode = (*cinfo->inputctl->consume_input) (cinfo);
+      if (retcode == JPEG_SUSPENDED)
+  return NULL;
+      if (retcode == JPEG_REACHED_EOI)
+  break;
+      /* Advance progress counter if appropriate */
+      if (cinfo->progress != NULL &&
+    (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
+  if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
+    /* startup underestimated number of scans; ratchet up one scan */
+    cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+  }
+      }
+    }
+    /* Set state so that jpeg_finish_decompress does the right thing */
+    cinfo->global_state = DSTATE_STOPPING;
+  }
+  /* At this point we should be in state DSTATE_STOPPING if being used
+   * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access
+   * to the coefficients during a full buffered-image-mode decompression.
+   */
+  if ((cinfo->global_state == DSTATE_STOPPING ||
+       cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) {
+    return ((j_lossy_d_ptr) cinfo->codec)->coef_arrays;
+  }
+  /* Oops, improper usage */
+  ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+  return NULL;      /* keep compiler happy */
+}
+
+
+/*
+ * Master selection of decompression modules for transcoding.
+ * This substitutes for jdmaster.c's initialization of the full decompressor.
+ */
+
+LOCAL(void)
+transdecode_master_selection (j_decompress_ptr cinfo)
+{
+  /* This is effectively a buffered-image operation. */
+  cinfo->buffered_image = TRUE;
+
+  /* Initialize decompression codec */
+  jinit_d_codec(cinfo);
+
+  /* We can now tell the memory manager to allocate virtual arrays. */
+  (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+  /* Initialize input side of decompressor to consume first scan. */
+  (*cinfo->inputctl->start_input_pass) (cinfo);
+
+  /* Initialize progress monitoring. */
+  if (cinfo->progress != NULL) {
+    int nscans;
+    /* Estimate number of scans to set pass_limit. */
+    if (cinfo->process == JPROC_PROGRESSIVE) {
+      /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
+      nscans = 2 + 3 * cinfo->num_components;
+    } else if (cinfo->inputctl->has_multiple_scans) {
+      /* For a nonprogressive multiscan file, estimate 1 scan per component. */
+      nscans = cinfo->num_components;
+    } else {
+      nscans = 1;
+    }
+    cinfo->progress->pass_counter = 0L;
+    cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+    cinfo->progress->completed_passes = 0;
+    cinfo->progress->total_passes = 1;
+  }
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jerror.c b/Utilities/ITK/Utilities/itkjpeg/jerror.c
new file mode 100644
index 0000000000000000000000000000000000000000..4e6e2e3515488c58c644fbef1e9eb22d38d0e5c3
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jerror.c
@@ -0,0 +1,252 @@
+/*
+ * jerror.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains simple error-reporting and trace-message routines.
+ * These are suitable for Unix-like systems and others where writing to
+ * stderr is the right thing to do.  Many applications will want to replace
+ * some or all of these routines.
+ *
+ * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile,
+ * you get a Windows-specific hack to display error messages in a dialog box.
+ * It ain't much, but it beats dropping error messages into the bit bucket,
+ * which is what happens to output to stderr under most Windows C compilers.
+ *
+ * These routines are used by both the compression and decompression code.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jversion.h"
+#include "jerror.h"
+
+#ifdef USE_WINDOWS_MESSAGEBOX
+#include <windows.h>
+#endif
+
+#ifndef EXIT_FAILURE    /* define exit() codes if not provided */
+#define EXIT_FAILURE  1
+#endif
+
+
+/*
+ * Create the message string table.
+ * We do this from the master message list in jerror.h by re-reading
+ * jerror.h with a suitable definition for macro JMESSAGE.
+ * The message table is made an external symbol just in case any applications
+ * want to refer to it directly.
+ */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_std_message_table  jMsgTable
+#endif
+
+#define JMESSAGE(code,string)  string ,
+
+const char * const jpeg_std_message_table[] = {
+#include "jerror.h"
+  NULL
+};
+
+
+/*
+ * Error exit handler: must not return to caller.
+ *
+ * Applications may override this if they want to get control back after
+ * an error.  Typically one would longjmp somewhere instead of exiting.
+ * The setjmp buffer can be made a private field within an expanded error
+ * handler object.  Note that the info needed to generate an error message
+ * is stored in the error object, so you can generate the message now or
+ * later, at your convenience.
+ * You should make sure that the JPEG object is cleaned up (with jpeg_abort
+ * or jpeg_destroy) at some point.
+ */
+
+METHODDEF(void)
+error_exit (j_common_ptr cinfo)
+{
+  /* Always display the message */
+  (*cinfo->err->output_message) (cinfo);
+
+  /* Let the memory manager delete any temp files before we die */
+  jpeg_destroy(cinfo);
+
+  exit(EXIT_FAILURE);
+}
+
+
+/*
+ * Actual output of an error or trace message.
+ * Applications may override this method to send JPEG messages somewhere
+ * other than stderr.
+ *
+ * On Windows, printing to stderr is generally completely useless,
+ * so we provide optional code to produce an error-dialog popup.
+ * Most Windows applications will still prefer to override this routine,
+ * but if they don't, it'll do something at least marginally useful.
+ *
+ * NOTE: to use the library in an environment that doesn't support the
+ * C stdio library, you may have to delete the call to fprintf() entirely,
+ * not just not use this routine.
+ */
+
+METHODDEF(void)
+output_message (j_common_ptr cinfo)
+{
+  char buffer[JMSG_LENGTH_MAX];
+
+  /* Create the message */
+  (*cinfo->err->format_message) (cinfo, buffer);
+
+#ifdef USE_WINDOWS_MESSAGEBOX
+  /* Display it in a message dialog box */
+  MessageBox(GetActiveWindow(), buffer, "JPEG Library Error",
+       MB_OK | MB_ICONERROR);
+#else
+  /* Send it to stderr, adding a newline */
+  fprintf(stderr, "%s\n", buffer);
+#endif
+}
+
+
+/*
+ * Decide whether to emit a trace or warning message.
+ * msg_level is one of:
+ *   -1: recoverable corrupt-data warning, may want to abort.
+ *    0: important advisory messages (always display to user).
+ *    1: first level of tracing detail.
+ *    2,3,...: successively more detailed tracing messages.
+ * An application might override this method if it wanted to abort on warnings
+ * or change the policy about which messages to display.
+ */
+
+METHODDEF(void)
+emit_message (j_common_ptr cinfo, int msg_level)
+{
+  struct jpeg_error_mgr * err = cinfo->err;
+
+  if (msg_level < 0) {
+    /* It's a warning message.  Since corrupt files may generate many warnings,
+     * the policy implemented here is to show only the first warning,
+     * unless trace_level >= 3.
+     */
+    if (err->num_warnings == 0 || err->trace_level >= 3)
+      (*err->output_message) (cinfo);
+    /* Always count warnings in num_warnings. */
+    err->num_warnings++;
+  } else {
+    /* It's a trace message.  Show it if trace_level >= msg_level. */
+    if (err->trace_level >= msg_level)
+      (*err->output_message) (cinfo);
+  }
+}
+
+
+/*
+ * Format a message string for the most recent JPEG error or message.
+ * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
+ * characters.  Note that no '\n' character is added to the string.
+ * Few applications should need to override this method.
+ */
+
+METHODDEF(void)
+format_message (j_common_ptr cinfo, char * buffer)
+{
+  struct jpeg_error_mgr * err = cinfo->err;
+  int msg_code = err->msg_code;
+  const char * msgtext = NULL;
+  const char * msgptr;
+  char ch;
+  boolean isstring;
+
+  /* Look up message string in proper table */
+  if (msg_code > 0 && msg_code <= err->last_jpeg_message) {
+    msgtext = err->jpeg_message_table[msg_code];
+  } else if (err->addon_message_table != NULL &&
+       msg_code >= err->first_addon_message &&
+       msg_code <= err->last_addon_message) {
+    msgtext = err->addon_message_table[msg_code - err->first_addon_message];
+  }
+
+  /* Defend against bogus message number */
+  if (msgtext == NULL) {
+    err->msg_parm.i[0] = msg_code;
+    msgtext = err->jpeg_message_table[0];
+  }
+
+  /* Check for string parameter, as indicated by %s in the message text */
+  isstring = FALSE;
+  msgptr = msgtext;
+  while ((ch = *msgptr++) != '\0') {
+    if (ch == '%') {
+      if (*msgptr == 's') isstring = TRUE;
+      break;
+    }
+  }
+
+  /* Format the message into the passed buffer */
+  if (isstring)
+    sprintf(buffer, msgtext, err->msg_parm.s);
+  else
+    sprintf(buffer, msgtext,
+      err->msg_parm.i[0], err->msg_parm.i[1],
+      err->msg_parm.i[2], err->msg_parm.i[3],
+      err->msg_parm.i[4], err->msg_parm.i[5],
+      err->msg_parm.i[6], err->msg_parm.i[7]);
+}
+
+
+/*
+ * Reset error state variables at start of a new image.
+ * This is called during compression startup to reset trace/error
+ * processing to default state, without losing any application-specific
+ * method pointers.  An application might possibly want to override
+ * this method if it has additional error processing state.
+ */
+
+METHODDEF(void)
+reset_error_mgr (j_common_ptr cinfo)
+{
+  cinfo->err->num_warnings = 0;
+  /* trace_level is not reset since it is an application-supplied parameter */
+  cinfo->err->msg_code = 0;  /* may be useful as a flag for "no error" */
+}
+
+
+/*
+ * Fill in the standard error-handling methods in a jpeg_error_mgr object.
+ * Typical call is:
+ *  struct jpeg_compress_struct cinfo;
+ *  struct jpeg_error_mgr err;
+ *
+ *  cinfo.err = jpeg_std_error(&err);
+ * after which the application may override some of the methods.
+ */
+
+GLOBAL(struct jpeg_error_mgr *)
+jpeg_std_error (struct jpeg_error_mgr * err)
+{
+  err->error_exit = error_exit;
+  err->emit_message = emit_message;
+  err->output_message = output_message;
+  err->format_message = format_message;
+  err->reset_error_mgr = reset_error_mgr;
+
+  err->trace_level = 0;    /* default = no tracing */
+  err->num_warnings = 0;  /* no warnings emitted yet */
+  err->msg_code = 0;    /* may be useful as a flag for "no error" */
+
+  /* Initialize message table pointers */
+  err->jpeg_message_table = jpeg_std_message_table;
+  err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
+
+  err->addon_message_table = NULL;
+  err->first_addon_message = 0;  /* for safety */
+  err->last_addon_message = 0;
+
+  return err;
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jerror.h b/Utilities/ITK/Utilities/itkjpeg/jerror.h
new file mode 100644
index 0000000000000000000000000000000000000000..d48ccfad091abac941478777fa4f0e10efbace4d
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jerror.h
@@ -0,0 +1,306 @@
+/*
+ * jerror.h
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the error and message codes for the JPEG library.
+ * Edit this file to add new codes, or to translate the message strings to
+ * some other language.
+ * A set of error-reporting macros are defined too.  Some applications using
+ * the JPEG library may wish to include this file to get the error codes
+ * and/or the macros.
+ */
+
+/*
+ * To define the enum list of message codes, include this file without
+ * defining macro JMESSAGE.  To create a message string table, include it
+ * again with a suitable JMESSAGE definition (see jerror.c for an example).
+ */
+#ifndef JMESSAGE
+#ifndef JERROR_H
+/* First time through, define the enum list */
+#define JMAKE_ENUM_LIST
+#else
+/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
+#define JMESSAGE(code,string)
+#endif /* JERROR_H */
+#endif /* JMESSAGE */
+
+#ifdef JMAKE_ENUM_LIST
+
+typedef enum {
+
+#define JMESSAGE(code,string)  code ,
+
+#endif /* JMAKE_ENUM_LIST */
+
+JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
+
+/* For maintenance convenience, list is alphabetical by message code name */
+JMESSAGE(JERR_ARITH_NOTIMPL,
+   "Sorry, there are legal restrictions on arithmetic coding")
+JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
+JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
+JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
+JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
+JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
+JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
+JMESSAGE(JERR_BAD_DIFF, "spatial difference out of range")
+JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
+JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
+JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
+JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
+JMESSAGE(JERR_BAD_LIB_VERSION,
+   "Wrong JPEG library version: library is %d, caller expects %d")
+JMESSAGE(JERR_BAD_LOSSLESS,
+   "Invalid lossless parameters Ss=%d Se=%d Ah=%d Al=%d")
+JMESSAGE(JERR_BAD_LOSSLESS_SCRIPT,
+   "Invalid lossless parameters at scan script entry %d")
+JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
+JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
+JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
+JMESSAGE(JERR_BAD_PROGRESSION,
+   "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
+JMESSAGE(JERR_BAD_PROG_SCRIPT,
+   "Invalid progressive parameters at scan script entry %d")
+JMESSAGE(JERR_BAD_RESTART, "Invalid restart interval: %d, must be an integer multiple of the number of MCUs in an MCU_row (%d)")
+JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
+JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
+JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
+JMESSAGE(JERR_BAD_STRUCT_SIZE,
+   "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
+JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
+JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
+JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
+JMESSAGE(JERR_CANT_TRANSCODE,
+   "Cannot transcode to/from lossless JPEG datastreams")
+JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
+JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
+JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
+JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
+JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
+JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
+JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
+JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
+JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
+JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
+JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
+JMESSAGE(JERR_FILE_READ, "Input file read error")
+JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
+JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
+JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
+JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
+JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
+JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
+JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
+JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
+   "Cannot transcode due to multiple use of quantization table %d")
+JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
+JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
+JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
+JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
+JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
+JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
+JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
+JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
+JMESSAGE(JERR_NO_LOSSLESS_SCRIPT, "Lossless encoding was requested but no scan script was supplied")
+JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
+JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
+JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
+JMESSAGE(JERR_QUANT_COMPONENTS,
+   "Cannot quantize more than %d color components")
+JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
+JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
+JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
+JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
+JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
+JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
+JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
+JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
+JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
+JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
+JMESSAGE(JERR_TFILE_WRITE,
+   "Write failed on temporary file --- out of disk space?")
+JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
+JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
+JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
+JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
+JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
+JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
+JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
+JMESSAGE(JMSG_VERSION, JVERSION)
+JMESSAGE(JTRC_16BIT_TABLES,
+   "Caution: quantization tables are too coarse for baseline JPEG")
+JMESSAGE(JTRC_ADOBE,
+   "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
+JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
+JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
+JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
+JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
+JMESSAGE(JTRC_DQT, "Define Quantization Table %d  precision %d")
+JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
+JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
+JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
+JMESSAGE(JTRC_EOI, "End Of Image")
+JMESSAGE(JTRC_HUFFBITS, "        %3d %3d %3d %3d %3d %3d %3d %3d")
+JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d  %d")
+JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
+   "Warning: thumbnail image size does not match data length %u")
+JMESSAGE(JTRC_JFIF_EXTENSION,
+   "JFIF extension marker: type 0x%02x, length %u")
+JMESSAGE(JTRC_JFIF_THUMBNAIL, "    with %d x %d thumbnail image")
+JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
+JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
+JMESSAGE(JTRC_QUANTVALS, "        %4u %4u %4u %4u %4u %4u %4u %4u")
+JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
+JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
+JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
+JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
+JMESSAGE(JTRC_RST, "RST%d")
+JMESSAGE(JTRC_SMOOTH_NOTIMPL,
+   "Smoothing not supported with nonstandard sampling ratios")
+JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
+JMESSAGE(JTRC_SOF_COMPONENT, "    Component %d: %dhx%dv q=%d")
+JMESSAGE(JTRC_SOI, "Start of Image")
+JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
+JMESSAGE(JTRC_SOS_COMPONENT, "    Component %d: dc=%d ac=%d")
+JMESSAGE(JTRC_SOS_PARAMS, "  Ss=%d, Se=%d, Ah=%d, Al=%d")
+JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
+JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
+JMESSAGE(JTRC_THUMB_JPEG,
+   "JFIF extension marker: JPEG-compressed thumbnail image, length %u")
+JMESSAGE(JTRC_THUMB_PALETTE,
+   "JFIF extension marker: palette thumbnail image, length %u")
+JMESSAGE(JTRC_THUMB_RGB,
+   "JFIF extension marker: RGB thumbnail image, length %u")
+JMESSAGE(JTRC_UNKNOWN_LOSSLESS_IDS,
+   "Unrecognized component IDs %d %d %d, assuming RGB")
+JMESSAGE(JTRC_UNKNOWN_LOSSY_IDS,
+   "Unrecognized component IDs %d %d %d, assuming YCbCr")
+JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
+JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
+JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
+JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
+JMESSAGE(JWRN_BOGUS_PROGRESSION,
+   "Inconsistent progression sequence for component %d coefficient %d")
+JMESSAGE(JWRN_EXTRANEOUS_DATA,
+   "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
+JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
+JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
+JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
+JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
+JMESSAGE(JWRN_MUST_DOWNSCALE,
+   "Must downscale data from %d bits to %d")
+JMESSAGE(JWRN_MUST_RESYNC,
+   "Corrupt JPEG data: found marker 0x%02x instead of RST%d")
+JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
+JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
+
+#ifdef JMAKE_ENUM_LIST
+
+  JMSG_LASTMSGCODE
+} J_MESSAGE_CODE;
+
+#undef JMAKE_ENUM_LIST
+#endif /* JMAKE_ENUM_LIST */
+
+/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
+#undef JMESSAGE
+
+
+#ifndef JERROR_H
+#define JERROR_H
+
+/* Macros to simplify using the error and trace message stuff */
+/* The first parameter is either type of cinfo pointer */
+
+/* Fatal errors (print message and exit) */
+#define ERREXIT(cinfo,code)  \
+  ((cinfo)->err->msg_code = (code), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT1(cinfo,code,p1)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT2(cinfo,code,p1,p2)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (cinfo)->err->msg_parm.i[1] = (p2), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT3(cinfo,code,p1,p2,p3)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (cinfo)->err->msg_parm.i[1] = (p2), \
+   (cinfo)->err->msg_parm.i[2] = (p3), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT4(cinfo,code,p1,p2,p3,p4)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (cinfo)->err->msg_parm.i[1] = (p2), \
+   (cinfo)->err->msg_parm.i[2] = (p3), \
+   (cinfo)->err->msg_parm.i[3] = (p4), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXITS(cinfo,code,str)  \
+  ((cinfo)->err->msg_code = (code), \
+   strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+   (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+
+#define MAKESTMT(stuff)    do { stuff } while (0)
+
+/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
+#define WARNMS(cinfo,code)  \
+  ((cinfo)->err->msg_code = (code), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+#define WARNMS1(cinfo,code,p1)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+#define WARNMS2(cinfo,code,p1,p2)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (cinfo)->err->msg_parm.i[1] = (p2), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+
+/* Informational/debugging messages */
+#define TRACEMS(cinfo,lvl,code)  \
+  ((cinfo)->err->msg_code = (code), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS1(cinfo,lvl,code,p1)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS2(cinfo,lvl,code,p1,p2)  \
+  ((cinfo)->err->msg_code = (code), \
+   (cinfo)->err->msg_parm.i[0] = (p1), \
+   (cinfo)->err->msg_parm.i[1] = (p2), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS3(cinfo,lvl,code,p1,p2,p3)  \
+  MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+     _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
+     (cinfo)->err->msg_code = (code); \
+     (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4)  \
+  MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+     _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+     (cinfo)->err->msg_code = (code); \
+     (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5)  \
+  MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+     _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+     _mp[4] = (p5); \
+     (cinfo)->err->msg_code = (code); \
+     (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8)  \
+  MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+     _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+     _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
+     (cinfo)->err->msg_code = (code); \
+     (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMSS(cinfo,lvl,code,str)  \
+  ((cinfo)->err->msg_code = (code), \
+   strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+   (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+
+#endif /* JERROR_H */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jfdctflt.c b/Utilities/ITK/Utilities/itkjpeg/jfdctflt.c
new file mode 100644
index 0000000000000000000000000000000000000000..f0297a2580ca118b6c8fc6c8e9d415f0306a7078
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jfdctflt.c
@@ -0,0 +1,168 @@
+/*
+ * jfdctflt.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a floating-point implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * This implementation should be more accurate than either of the integer
+ * DCT implementations.  However, it may not give the same results on all
+ * machines because of differences in roundoff behavior.  Speed will depend
+ * on the hardware's floating point capacity.
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column.  Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT.  Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README).  The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs.  These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries.  The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with a fixed-point
+ * implementation, accuracy is lost due to imprecise representation of the
+ * scaled quantization values.  However, that problem does not arise if
+ * we use floating point arithmetic.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h"    /* Private declarations for DCT subsystem */
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+  Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_float (FAST_FLOAT * data)
+{
+  FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+  FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
+  FAST_FLOAT z1, z2, z3, z4, z5, z11, z13;
+  FAST_FLOAT *dataptr;
+  int ctr;
+
+  /* Pass 1: process rows. */
+
+  dataptr = data;
+  for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+    tmp0 = dataptr[0] + dataptr[7];
+    tmp7 = dataptr[0] - dataptr[7];
+    tmp1 = dataptr[1] + dataptr[6];
+    tmp6 = dataptr[1] - dataptr[6];
+    tmp2 = dataptr[2] + dataptr[5];
+    tmp5 = dataptr[2] - dataptr[5];
+    tmp3 = dataptr[3] + dataptr[4];
+    tmp4 = dataptr[3] - dataptr[4];
+    
+    /* Even part */
+    
+    tmp10 = tmp0 + tmp3;  /* phase 2 */
+    tmp13 = tmp0 - tmp3;
+    tmp11 = tmp1 + tmp2;
+    tmp12 = tmp1 - tmp2;
+    
+    dataptr[0] = tmp10 + tmp11; /* phase 3 */
+    dataptr[4] = tmp10 - tmp11;
+    
+    z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
+    dataptr[2] = tmp13 + z1;  /* phase 5 */
+    dataptr[6] = tmp13 - z1;
+    
+    /* Odd part */
+
+    tmp10 = tmp4 + tmp5;  /* phase 2 */
+    tmp11 = tmp5 + tmp6;
+    tmp12 = tmp6 + tmp7;
+
+    /* The rotator is modified from fig 4-8 to avoid extra negations. */
+    z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
+    z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
+    z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
+    z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+
+    z11 = tmp7 + z3;    /* phase 5 */
+    z13 = tmp7 - z3;
+
+    dataptr[5] = z13 + z2;  /* phase 6 */
+    dataptr[3] = z13 - z2;
+    dataptr[1] = z11 + z4;
+    dataptr[7] = z11 - z4;
+
+    dataptr += DCTSIZE;    /* advance pointer to next row */
+  }
+
+  /* Pass 2: process columns. */
+
+  dataptr = data;
+  for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+    tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+    tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+    tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+    tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+    tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+    tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+    tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+    tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+    
+    /* Even part */
+    
+    tmp10 = tmp0 + tmp3;  /* phase 2 */
+    tmp13 = tmp0 - tmp3;
+    tmp11 = tmp1 + tmp2;
+    tmp12 = tmp1 - tmp2;
+    
+    dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
+    dataptr[DCTSIZE*4] = tmp10 - tmp11;
+    
+    z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
+    dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
+    dataptr[DCTSIZE*6] = tmp13 - z1;
+    
+    /* Odd part */
+
+    tmp10 = tmp4 + tmp5;  /* phase 2 */
+    tmp11 = tmp5 + tmp6;
+    tmp12 = tmp6 + tmp7;
+
+    /* The rotator is modified from fig 4-8 to avoid extra negations. */
+    z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
+    z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
+    z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
+    z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+
+    z11 = tmp7 + z3;    /* phase 5 */
+    z13 = tmp7 - z3;
+
+    dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
+    dataptr[DCTSIZE*3] = z13 - z2;
+    dataptr[DCTSIZE*1] = z11 + z4;
+    dataptr[DCTSIZE*7] = z11 - z4;
+
+    dataptr++;      /* advance pointer to next column */
+  }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jfdctfst.c b/Utilities/ITK/Utilities/itkjpeg/jfdctfst.c
new file mode 100644
index 0000000000000000000000000000000000000000..5d51e3c177e9d587d2580cb889dabb6a6a0954e3
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jfdctfst.c
@@ -0,0 +1,224 @@
+/*
+ * jfdctfst.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a fast, not so accurate integer implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column.  Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT.  Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README).  The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs.  These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries.  The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with fixed-point math,
+ * accuracy is lost due to imprecise representation of the scaled
+ * quantization values.  The smaller the quantization table entry, the less
+ * precise the scaled value, so this implementation does worse with high-
+ * quality-setting files than with low-quality ones.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h"    /* Private declarations for DCT subsystem */
+
+#ifdef DCT_IFAST_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+  Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling decisions are generally the same as in the LL&M algorithm;
+ * see jfdctint.c for more details.  However, we choose to descale
+ * (right shift) multiplication products as soon as they are formed,
+ * rather than carrying additional fractional bits into subsequent additions.
+ * This compromises accuracy slightly, but it lets us save a few shifts.
+ * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
+ * everywhere except in the multiplications proper; this saves a good deal
+ * of work on 16-bit-int machines.
+ *
+ * Again to save a few shifts, the intermediate results between pass 1 and
+ * pass 2 are not upscaled, but are represented only to integral precision.
+ *
+ * A final compromise is to represent the multiplicative constants to only
+ * 8 fractional bits, rather than 13.  This saves some shifting work on some
+ * machines, and may also reduce the cost of multiplication (since there
+ * are fewer one-bits in the constants).
+ */
+
+#define CONST_BITS  8
+
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 8
+#define FIX_0_382683433  ((INT32)   98)    /* FIX(0.382683433) */
+#define FIX_0_541196100  ((INT32)  139)    /* FIX(0.541196100) */
+#define FIX_0_707106781  ((INT32)  181)    /* FIX(0.707106781) */
+#define FIX_1_306562965  ((INT32)  334)    /* FIX(1.306562965) */
+#else
+#define FIX_0_382683433  FIX(0.382683433)
+#define FIX_0_541196100  FIX(0.541196100)
+#define FIX_0_707106781  FIX(0.707106781)
+#define FIX_1_306562965  FIX(1.306562965)
+#endif
+
+
+/* We can gain a little more speed, with a further compromise in accuracy,
+ * by omitting the addition in a descaling shift.  This yields an incorrectly
+ * rounded result half the time...
+ */
+
+#ifndef USE_ACCURATE_ROUNDING
+#undef DESCALE
+#define DESCALE(x,n)  RIGHT_SHIFT(x, n)
+#endif
+
+
+/* Multiply a DCTELEM variable by an INT32 constant, and immediately
+ * descale to yield a DCTELEM result.
+ */
+
+#define MULTIPLY(var,const)  ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_ifast (DCTELEM * data)
+{
+  DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+  DCTELEM tmp10, tmp11, tmp12, tmp13;
+  DCTELEM z1, z2, z3, z4, z5, z11, z13;
+  DCTELEM *dataptr;
+  int ctr;
+  SHIFT_TEMPS
+
+  /* Pass 1: process rows. */
+
+  dataptr = data;
+  for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+    tmp0 = dataptr[0] + dataptr[7];
+    tmp7 = dataptr[0] - dataptr[7];
+    tmp1 = dataptr[1] + dataptr[6];
+    tmp6 = dataptr[1] - dataptr[6];
+    tmp2 = dataptr[2] + dataptr[5];
+    tmp5 = dataptr[2] - dataptr[5];
+    tmp3 = dataptr[3] + dataptr[4];
+    tmp4 = dataptr[3] - dataptr[4];
+    
+    /* Even part */
+    
+    tmp10 = tmp0 + tmp3;  /* phase 2 */
+    tmp13 = tmp0 - tmp3;
+    tmp11 = tmp1 + tmp2;
+    tmp12 = tmp1 - tmp2;
+    
+    dataptr[0] = tmp10 + tmp11; /* phase 3 */
+    dataptr[4] = tmp10 - tmp11;
+    
+    z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
+    dataptr[2] = tmp13 + z1;  /* phase 5 */
+    dataptr[6] = tmp13 - z1;
+    
+    /* Odd part */
+
+    tmp10 = tmp4 + tmp5;  /* phase 2 */
+    tmp11 = tmp5 + tmp6;
+    tmp12 = tmp6 + tmp7;
+
+    /* The rotator is modified from fig 4-8 to avoid extra negations. */
+    z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
+    z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
+    z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
+    z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
+
+    z11 = tmp7 + z3;    /* phase 5 */
+    z13 = tmp7 - z3;
+
+    dataptr[5] = z13 + z2;  /* phase 6 */
+    dataptr[3] = z13 - z2;
+    dataptr[1] = z11 + z4;
+    dataptr[7] = z11 - z4;
+
+    dataptr += DCTSIZE;    /* advance pointer to next row */
+  }
+
+  /* Pass 2: process columns. */
+
+  dataptr = data;
+  for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+    tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+    tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+    tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+    tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+    tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+    tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+    tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+    tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+    
+    /* Even part */
+    
+    tmp10 = tmp0 + tmp3;  /* phase 2 */
+    tmp13 = tmp0 - tmp3;
+    tmp11 = tmp1 + tmp2;
+    tmp12 = tmp1 - tmp2;
+    
+    dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
+    dataptr[DCTSIZE*4] = tmp10 - tmp11;
+    
+    z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
+    dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
+    dataptr[DCTSIZE*6] = tmp13 - z1;
+    
+    /* Odd part */
+
+    tmp10 = tmp4 + tmp5;  /* phase 2 */
+    tmp11 = tmp5 + tmp6;
+    tmp12 = tmp6 + tmp7;
+
+    /* The rotator is modified from fig 4-8 to avoid extra negations. */
+    z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
+    z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
+    z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
+    z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
+
+    z11 = tmp7 + z3;    /* phase 5 */
+    z13 = tmp7 - z3;
+
+    dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
+    dataptr[DCTSIZE*3] = z13 - z2;
+    dataptr[DCTSIZE*1] = z11 + z4;
+    dataptr[DCTSIZE*7] = z11 - z4;
+
+    dataptr++;      /* advance pointer to next column */
+  }
+}
+
+#endif /* DCT_IFAST_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jfdctint.c b/Utilities/ITK/Utilities/itkjpeg/jfdctint.c
new file mode 100644
index 0000000000000000000000000000000000000000..8f6c73db3b926e01469cd503fb950c84edc97eab
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jfdctint.c
@@ -0,0 +1,283 @@
+/*
+ * jfdctint.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a slow-but-accurate integer implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column.  Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on an algorithm described in
+ *   C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
+ *   Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
+ *   Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
+ * The primary algorithm described there uses 11 multiplies and 29 adds.
+ * We use their alternate method with 12 multiplies and 32 adds.
+ * The advantage of this method is that no data path contains more than one
+ * multiplication; this allows a very simple and accurate implementation in
+ * scaled fixed-point arithmetic, with a minimal number of shifts.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h"    /* Private declarations for DCT subsystem */
+
+#ifdef DCT_ISLOW_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+  Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D DCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true DCT outputs.  The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm.  The advantage of
+ * this arrangement is that we save two multiplications per 1-D DCT,
+ * because the y0 and y4 outputs need not be divided by sqrt(N).
+ * In the IJG code, this factor of 8 is removed by the quantization step
+ * (in jcdctmgr.c), NOT in this module.
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic.  We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants).  After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output.  This division can be done
+ * cheaply as a right shift of CONST_BITS bits.  We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision.  These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling.  (For 12-bit sample data, the intermediate
+ * array is INT32 anyway.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26.  Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS  13
+#define PASS1_BITS  2
+#else
+#define CONST_BITS  13
+#define PASS1_BITS  1    /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_298631336  ((INT32)  2446)  /* FIX(0.298631336) */
+#define FIX_0_390180644  ((INT32)  3196)  /* FIX(0.390180644) */
+#define FIX_0_541196100  ((INT32)  4433)  /* FIX(0.541196100) */
+#define FIX_0_765366865  ((INT32)  6270)  /* FIX(0.765366865) */
+#define FIX_0_899976223  ((INT32)  7373)  /* FIX(0.899976223) */
+#define FIX_1_175875602  ((INT32)  9633)  /* FIX(1.175875602) */
+#define FIX_1_501321110  ((INT32)  12299)  /* FIX(1.501321110) */
+#define FIX_1_847759065  ((INT32)  15137)  /* FIX(1.847759065) */
+#define FIX_1_961570560  ((INT32)  16069)  /* FIX(1.961570560) */
+#define FIX_2_053119869  ((INT32)  16819)  /* FIX(2.053119869) */
+#define FIX_2_562915447  ((INT32)  20995)  /* FIX(2.562915447) */
+#define FIX_3_072711026  ((INT32)  25172)  /* FIX(3.072711026) */
+#else
+#define FIX_0_298631336  FIX(0.298631336)
+#define FIX_0_390180644  FIX(0.390180644)
+#define FIX_0_541196100  FIX(0.541196100)
+#define FIX_0_765366865  FIX(0.765366865)
+#define FIX_0_899976223  FIX(0.899976223)
+#define FIX_1_175875602  FIX(1.175875602)
+#define FIX_1_501321110  FIX(1.501321110)
+#define FIX_1_847759065  FIX(1.847759065)
+#define FIX_1_961570560  FIX(1.961570560)
+#define FIX_2_053119869  FIX(2.053119869)
+#define FIX_2_562915447  FIX(2.562915447)
+#define FIX_3_072711026  FIX(3.072711026)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const)  MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const)  ((var) * (const))
+#endif
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_islow (DCTELEM * data)
+{
+  INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+  INT32 tmp10, tmp11, tmp12, tmp13;
+  INT32 z1, z2, z3, z4, z5;
+  DCTELEM *dataptr;
+  int ctr;
+  SHIFT_TEMPS
+
+  /* Pass 1: process rows. */
+  /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+  /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+  dataptr = data;
+  for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+    tmp0 = dataptr[0] + dataptr[7];
+    tmp7 = dataptr[0] - dataptr[7];
+    tmp1 = dataptr[1] + dataptr[6];
+    tmp6 = dataptr[1] - dataptr[6];
+    tmp2 = dataptr[2] + dataptr[5];
+    tmp5 = dataptr[2] - dataptr[5];
+    tmp3 = dataptr[3] + dataptr[4];
+    tmp4 = dataptr[3] - dataptr[4];
+    
+    /* Even part per LL&M figure 1 --- note that published figure is faulty;
+     * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+     */
+    
+    tmp10 = tmp0 + tmp3;
+    tmp13 = tmp0 - tmp3;
+    tmp11 = tmp1 + tmp2;
+    tmp12 = tmp1 - tmp2;
+    
+    dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS);
+    dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS);
+    
+    z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+    dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+           CONST_BITS-PASS1_BITS);
+    dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
+           CONST_BITS-PASS1_BITS);
+    
+    /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+     * cK represents cos(K*pi/16).
+     * i0..i3 in the paper are tmp4..tmp7 here.
+     */
+    
+    z1 = tmp4 + tmp7;
+    z2 = tmp5 + tmp6;
+    z3 = tmp4 + tmp6;
+    z4 = tmp5 + tmp7;
+    z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+    
+    tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+    tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+    tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+    tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+    z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+    z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+    z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+    z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+    
+    z3 += z5;
+    z4 += z5;
+    
+    dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS);
+    dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS);
+    dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS);
+    dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS);
+    
+    dataptr += DCTSIZE;    /* advance pointer to next row */
+  }
+
+  /* Pass 2: process columns.
+   * We remove the PASS1_BITS scaling, but leave the results scaled up
+   * by an overall factor of 8.
+   */
+
+  dataptr = data;
+  for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+    tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+    tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+    tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+    tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+    tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+    tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+    tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+    tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+    
+    /* Even part per LL&M figure 1 --- note that published figure is faulty;
+     * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+     */
+    
+    tmp10 = tmp0 + tmp3;
+    tmp13 = tmp0 - tmp3;
+    tmp11 = tmp1 + tmp2;
+    tmp12 = tmp1 - tmp2;
+    
+    dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS);
+    dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
+    
+    z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+    dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+             CONST_BITS+PASS1_BITS);
+    dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
+             CONST_BITS+PASS1_BITS);
+    
+    /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+     * cK represents cos(K*pi/16).
+     * i0..i3 in the paper are tmp4..tmp7 here.
+     */
+    
+    z1 = tmp4 + tmp7;
+    z2 = tmp5 + tmp6;
+    z3 = tmp4 + tmp6;
+    z4 = tmp5 + tmp7;
+    z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+    
+    tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+    tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+    tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+    tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+    z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+    z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+    z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+    z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+    
+    z3 += z5;
+    z4 += z5;
+    
+    dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3,
+             CONST_BITS+PASS1_BITS);
+    dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4,
+             CONST_BITS+PASS1_BITS);
+    dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3,
+             CONST_BITS+PASS1_BITS);
+    dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4,
+             CONST_BITS+PASS1_BITS);
+    
+    dataptr++;      /* advance pointer to next column */
+  }
+}
+
+#endif /* DCT_ISLOW_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jidctflt.c b/Utilities/ITK/Utilities/itkjpeg/jidctflt.c
new file mode 100644
index 0000000000000000000000000000000000000000..0d72de891b8a1bad1d589f997c423aa045fcc5ca
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jidctflt.c
@@ -0,0 +1,242 @@
+/*
+ * jidctflt.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a floating-point implementation of the
+ * inverse DCT (Discrete Cosine Transform).  In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * This implementation should be more accurate than either of the integer
+ * IDCT implementations.  However, it may not give the same results on all
+ * machines because of differences in roundoff behavior.  Speed will depend
+ * on the hardware's floating point capacity.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time).  Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT.  Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README).  The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs.  These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries.  The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with a fixed-point
+ * implementation, accuracy is lost due to imprecise representation of the
+ * scaled quantization values.  However, that problem does not arise if
+ * we use floating point arithmetic.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h"    /* Private declarations for DCT subsystem */
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+  Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce a float result.
+ */
+
+#define DEQUANTIZE(coef,quantval)  (((FAST_FLOAT) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+     JCOEFPTR coef_block,
+     JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+  FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+  FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
+  FAST_FLOAT z5, z10, z11, z12, z13;
+  JCOEFPTR inptr;
+  FLOAT_MULT_TYPE * quantptr;
+  FAST_FLOAT * wsptr;
+  JSAMPROW outptr;
+  JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+  int ctr;
+  FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
+  SHIFT_TEMPS
+
+  /* Pass 1: process columns from input, store into work array. */
+
+  inptr = coef_block;
+  quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table;
+  wsptr = workspace;
+  for (ctr = DCTSIZE; ctr > 0; ctr--) {
+    /* Due to quantization, we will usually find that many of the input
+     * coefficients are zero, especially the AC terms.  We can exploit this
+     * by short-circuiting the IDCT calculation for any column in which all
+     * the AC terms are zero.  In that case each output is equal to the
+     * DC coefficient (with scale factor as needed).
+     * With typical images and quantization tables, half or more of the
+     * column DCT calculations can be simplified this way.
+     */
+    
+    if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+  inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+  inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+  inptr[DCTSIZE*7] == 0) {
+      /* AC terms all zero */
+      FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+      
+      wsptr[DCTSIZE*0] = dcval;
+      wsptr[DCTSIZE*1] = dcval;
+      wsptr[DCTSIZE*2] = dcval;
+      wsptr[DCTSIZE*3] = dcval;
+      wsptr[DCTSIZE*4] = dcval;
+      wsptr[DCTSIZE*5] = dcval;
+      wsptr[DCTSIZE*6] = dcval;
+      wsptr[DCTSIZE*7] = dcval;
+      
+      inptr++;      /* advance pointers to next column */
+      quantptr++;
+      wsptr++;
+      continue;
+    }
+    
+    /* Even part */
+
+    tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+    tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+    tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+    tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+    tmp10 = tmp0 + tmp2;  /* phase 3 */
+    tmp11 = tmp0 - tmp2;
+
+    tmp13 = tmp1 + tmp3;  /* phases 5-3 */
+    tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
+
+    tmp0 = tmp10 + tmp13;  /* phase 2 */
+    tmp3 = tmp10 - tmp13;
+    tmp1 = tmp11 + tmp12;
+    tmp2 = tmp11 - tmp12;
+    
+    /* Odd part */
+
+    tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+    tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+    tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+    tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+    z13 = tmp6 + tmp5;    /* phase 6 */
+    z10 = tmp6 - tmp5;
+    z11 = tmp4 + tmp7;
+    z12 = tmp4 - tmp7;
+
+    tmp7 = z11 + z13;    /* phase 5 */
+    tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
+
+    z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
+    tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
+    tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
+
+    tmp6 = tmp12 - tmp7;  /* phase 2 */
+    tmp5 = tmp11 - tmp6;
+    tmp4 = tmp10 + tmp5;
+
+    wsptr[DCTSIZE*0] = tmp0 + tmp7;
+    wsptr[DCTSIZE*7] = tmp0 - tmp7;
+    wsptr[DCTSIZE*1] = tmp1 + tmp6;
+    wsptr[DCTSIZE*6] = tmp1 - tmp6;
+    wsptr[DCTSIZE*2] = tmp2 + tmp5;
+    wsptr[DCTSIZE*5] = tmp2 - tmp5;
+    wsptr[DCTSIZE*4] = tmp3 + tmp4;
+    wsptr[DCTSIZE*3] = tmp3 - tmp4;
+
+    inptr++;      /* advance pointers to next column */
+    quantptr++;
+    wsptr++;
+  }
+  
+  /* Pass 2: process rows from work array, store into output array. */
+  /* Note that we must descale the results by a factor of 8 == 2**3. */
+
+  wsptr = workspace;
+  for (ctr = 0; ctr < DCTSIZE; ctr++) {
+    outptr = output_buf[ctr] + output_col;
+    /* Rows of zeroes can be exploited in the same way as we did with columns.
+     * However, the column calculation has created many nonzero AC terms, so
+     * the simplification applies less often (typically 5% to 10% of the time).
+     * And testing floats for zero is relatively expensive, so we don't bother.
+     */
+    
+    /* Even part */
+
+    tmp10 = wsptr[0] + wsptr[4];
+    tmp11 = wsptr[0] - wsptr[4];
+
+    tmp13 = wsptr[2] + wsptr[6];
+    tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
+
+    tmp0 = tmp10 + tmp13;
+    tmp3 = tmp10 - tmp13;
+    tmp1 = tmp11 + tmp12;
+    tmp2 = tmp11 - tmp12;
+
+    /* Odd part */
+
+    z13 = wsptr[5] + wsptr[3];
+    z10 = wsptr[5] - wsptr[3];
+    z11 = wsptr[1] + wsptr[7];
+    z12 = wsptr[1] - wsptr[7];
+
+    tmp7 = z11 + z13;
+    tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
+
+    z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
+    tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
+    tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
+
+    tmp6 = tmp12 - tmp7;
+    tmp5 = tmp11 - tmp6;
+    tmp4 = tmp10 + tmp5;
+
+    /* Final output stage: scale down by a factor of 8 and range-limit */
+
+    outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3)
+          & RANGE_MASK];
+    outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3)
+          & RANGE_MASK];
+    outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3)
+          & RANGE_MASK];
+    outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3)
+          & RANGE_MASK];
+    outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3)
+          & RANGE_MASK];
+    outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3)
+          & RANGE_MASK];
+    outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3)
+          & RANGE_MASK];
+    outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3)
+          & RANGE_MASK];
+    
+    wsptr += DCTSIZE;    /* advance pointer to next row */
+  }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jidctfst.c b/Utilities/ITK/Utilities/itkjpeg/jidctfst.c
new file mode 100644
index 0000000000000000000000000000000000000000..3245decc45fd1418b5862cab566070b28a3d5613
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jidctfst.c
@@ -0,0 +1,368 @@
+/*
+ * jidctfst.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a fast, not so accurate integer implementation of the
+ * inverse DCT (Discrete Cosine Transform).  In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time).  Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT.  Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README).  The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs.  These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries.  The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with fixed-point math,
+ * accuracy is lost due to imprecise representation of the scaled
+ * quantization values.  The smaller the quantization table entry, the less
+ * precise the scaled value, so this implementation does worse with high-
+ * quality-setting files than with low-quality ones.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h"    /* Private declarations for DCT subsystem */
+
+#ifdef DCT_IFAST_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+  Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling decisions are generally the same as in the LL&M algorithm;
+ * see jidctint.c for more details.  However, we choose to descale
+ * (right shift) multiplication products as soon as they are formed,
+ * rather than carrying additional fractional bits into subsequent additions.
+ * This compromises accuracy slightly, but it lets us save a few shifts.
+ * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
+ * everywhere except in the multiplications proper; this saves a good deal
+ * of work on 16-bit-int machines.
+ *
+ * The dequantized coefficients are not integers because the AA&N scaling
+ * factors have been incorporated.  We represent them scaled up by PASS1_BITS,
+ * so that the first and second IDCT rounds have the same input scaling.
+ * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to
+ * avoid a descaling shift; this compromises accuracy rather drastically
+ * for small quantization table entries, but it saves a lot of shifts.
+ * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway,
+ * so we use a much larger scaling factor to preserve accuracy.
+ *
+ * A final compromise is to represent the multiplicative constants to only
+ * 8 fractional bits, rather than 13.  This saves some shifting work on some
+ * machines, and may also reduce the cost of multiplication (since there
+ * are fewer one-bits in the constants).
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS  8
+#define PASS1_BITS  2
+#else
+#define CONST_BITS  8
+#define PASS1_BITS  1    /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 8
+#define FIX_1_082392200  ((INT32)  277)    /* FIX(1.082392200) */
+#define FIX_1_414213562  ((INT32)  362)    /* FIX(1.414213562) */
+#define FIX_1_847759065  ((INT32)  473)    /* FIX(1.847759065) */
+#define FIX_2_613125930  ((INT32)  669)    /* FIX(2.613125930) */
+#else
+#define FIX_1_082392200  FIX(1.082392200)
+#define FIX_1_414213562  FIX(1.414213562)
+#define FIX_1_847759065  FIX(1.847759065)
+#define FIX_2_613125930  FIX(2.613125930)
+#endif
+
+
+/* We can gain a little more speed, with a further compromise in accuracy,
+ * by omitting the addition in a descaling shift.  This yields an incorrectly
+ * rounded result half the time...
+ */
+
+#ifndef USE_ACCURATE_ROUNDING
+#undef DESCALE
+#define DESCALE(x,n)  RIGHT_SHIFT(x, n)
+#endif
+
+
+/* Multiply a DCTELEM variable by an INT32 constant, and immediately
+ * descale to yield a DCTELEM result.
+ */
+
+#define MULTIPLY(var,const)  ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce a DCTELEM result.  For 8-bit data a 16x16->16
+ * multiplication will do.  For 12-bit data, the multiplier table is
+ * declared INT32, so a 32-bit multiply will be used.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define DEQUANTIZE(coef,quantval)  (((IFAST_MULT_TYPE) (coef)) * (quantval))
+#else
+#define DEQUANTIZE(coef,quantval)  \
+  DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS)
+#endif
+
+
+/* Like DESCALE, but applies to a DCTELEM and produces an int.
+ * We assume that int right shift is unsigned if INT32 right shift is.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define ISHIFT_TEMPS  DCTELEM ishift_temp;
+#if BITS_IN_JSAMPLE == 8
+#define DCTELEMBITS  16    /* DCTELEM may be 16 or 32 bits */
+#else
+#define DCTELEMBITS  32    /* DCTELEM must be 32 bits */
+#endif
+#define IRIGHT_SHIFT(x,shft)  \
+    ((ishift_temp = (x)) < 0 ? \
+     (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \
+     (ishift_temp >> (shft)))
+#else
+#define ISHIFT_TEMPS
+#define IRIGHT_SHIFT(x,shft)  ((x) >> (shft))
+#endif
+
+#ifdef USE_ACCURATE_ROUNDING
+#define IDESCALE(x,n)  ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n))
+#else
+#define IDESCALE(x,n)  ((int) IRIGHT_SHIFT(x, n))
+#endif
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+     JCOEFPTR coef_block,
+     JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+  DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+  DCTELEM tmp10, tmp11, tmp12, tmp13;
+  DCTELEM z5, z10, z11, z12, z13;
+  JCOEFPTR inptr;
+  IFAST_MULT_TYPE * quantptr;
+  int * wsptr;
+  JSAMPROW outptr;
+  JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+  int ctr;
+  int workspace[DCTSIZE2];  /* buffers data between passes */
+  SHIFT_TEMPS      /* for DESCALE */
+  ISHIFT_TEMPS      /* for IDESCALE */
+
+  /* Pass 1: process columns from input, store into work array. */
+
+  inptr = coef_block;
+  quantptr = (IFAST_MULT_TYPE *) compptr->dct_table;
+  wsptr = workspace;
+  for (ctr = DCTSIZE; ctr > 0; ctr--) {
+    /* Due to quantization, we will usually find that many of the input
+     * coefficients are zero, especially the AC terms.  We can exploit this
+     * by short-circuiting the IDCT calculation for any column in which all
+     * the AC terms are zero.  In that case each output is equal to the
+     * DC coefficient (with scale factor as needed).
+     * With typical images and quantization tables, half or more of the
+     * column DCT calculations can be simplified this way.
+     */
+    
+    if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+  inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+  inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+  inptr[DCTSIZE*7] == 0) {
+      /* AC terms all zero */
+      int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+
+      wsptr[DCTSIZE*0] = dcval;
+      wsptr[DCTSIZE*1] = dcval;
+      wsptr[DCTSIZE*2] = dcval;
+      wsptr[DCTSIZE*3] = dcval;
+      wsptr[DCTSIZE*4] = dcval;
+      wsptr[DCTSIZE*5] = dcval;
+      wsptr[DCTSIZE*6] = dcval;
+      wsptr[DCTSIZE*7] = dcval;
+      
+      inptr++;      /* advance pointers to next column */
+      quantptr++;
+      wsptr++;
+      continue;
+    }
+    
+    /* Even part */
+
+    tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+    tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+    tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+    tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+    tmp10 = tmp0 + tmp2;  /* phase 3 */
+    tmp11 = tmp0 - tmp2;
+
+    tmp13 = tmp1 + tmp3;  /* phases 5-3 */
+    tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */
+
+    tmp0 = tmp10 + tmp13;  /* phase 2 */
+    tmp3 = tmp10 - tmp13;
+    tmp1 = tmp11 + tmp12;
+    tmp2 = tmp11 - tmp12;
+    
+    /* Odd part */
+
+    tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+    tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+    tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+    tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+    z13 = tmp6 + tmp5;    /* phase 6 */
+    z10 = tmp6 - tmp5;
+    z11 = tmp4 + tmp7;
+    z12 = tmp4 - tmp7;
+
+    tmp7 = z11 + z13;    /* phase 5 */
+    tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
+
+    z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
+    tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
+    tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+
+    tmp6 = tmp12 - tmp7;  /* phase 2 */
+    tmp5 = tmp11 - tmp6;
+    tmp4 = tmp10 + tmp5;
+
+    wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7);
+    wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7);
+    wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6);
+    wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6);
+    wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5);
+    wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5);
+    wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4);
+    wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4);
+
+    inptr++;      /* advance pointers to next column */
+    quantptr++;
+    wsptr++;
+  }
+  
+  /* Pass 2: process rows from work array, store into output array. */
+  /* Note that we must descale the results by a factor of 8 == 2**3, */
+  /* and also undo the PASS1_BITS scaling. */
+
+  wsptr = workspace;
+  for (ctr = 0; ctr < DCTSIZE; ctr++) {
+    outptr = output_buf[ctr] + output_col;
+    /* Rows of zeroes can be exploited in the same way as we did with columns.
+     * However, the column calculation has created many nonzero AC terms, so
+     * the simplification applies less often (typically 5% to 10% of the time).
+     * On machines with very fast multiplication, it's possible that the
+     * test takes more time than it's worth.  In that case this section
+     * may be commented out.
+     */
+    
+#ifndef NO_ZERO_ROW_TEST
+    if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
+  wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+      /* AC terms all zero */
+      JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3)
+          & RANGE_MASK];
+      
+      outptr[0] = dcval;
+      outptr[1] = dcval;
+      outptr[2] = dcval;
+      outptr[3] = dcval;
+      outptr[4] = dcval;
+      outptr[5] = dcval;
+      outptr[6] = dcval;
+      outptr[7] = dcval;
+
+      wsptr += DCTSIZE;    /* advance pointer to next row */
+      continue;
+    }
+#endif
+    
+    /* Even part */
+
+    tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]);
+    tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]);
+
+    tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]);
+    tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562)
+      - tmp13;
+
+    tmp0 = tmp10 + tmp13;
+    tmp3 = tmp10 - tmp13;
+    tmp1 = tmp11 + tmp12;
+    tmp2 = tmp11 - tmp12;
+
+    /* Odd part */
+
+    z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3];
+    z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3];
+    z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7];
+    z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7];
+
+    tmp7 = z11 + z13;    /* phase 5 */
+    tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
+
+    z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
+    tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
+    tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+
+    tmp6 = tmp12 - tmp7;  /* phase 2 */
+    tmp5 = tmp11 - tmp6;
+    tmp4 = tmp10 + tmp5;
+
+    /* Final output stage: scale down by a factor of 8 and range-limit */
+
+    outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3)
+          & RANGE_MASK];
+
+    wsptr += DCTSIZE;    /* advance pointer to next row */
+  }
+}
+
+#endif /* DCT_IFAST_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jidctint.c b/Utilities/ITK/Utilities/itkjpeg/jidctint.c
new file mode 100644
index 0000000000000000000000000000000000000000..e8a8b7af5707e465c85d7044e9b85e69ea058e9b
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jidctint.c
@@ -0,0 +1,389 @@
+/*
+ * jidctint.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a slow-but-accurate integer implementation of the
+ * inverse DCT (Discrete Cosine Transform).  In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time).  Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on an algorithm described in
+ *   C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
+ *   Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
+ *   Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
+ * The primary algorithm described there uses 11 multiplies and 29 adds.
+ * We use their alternate method with 12 multiplies and 32 adds.
+ * The advantage of this method is that no data path contains more than one
+ * multiplication; this allows a very simple and accurate implementation in
+ * scaled fixed-point arithmetic, with a minimal number of shifts.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h"    /* Private declarations for DCT subsystem */
+
+#ifdef DCT_ISLOW_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+  Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true IDCT outputs.  The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm.  The advantage of
+ * this arrangement is that we save two multiplications per 1-D IDCT,
+ * because the y0 and y4 inputs need not be divided by sqrt(N).
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic.  We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants).  After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output.  This division can be done
+ * cheaply as a right shift of CONST_BITS bits.  We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision.  These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling.  (To scale up 12-bit sample data further, an
+ * intermediate INT32 array would be needed.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26.  Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS  13
+#define PASS1_BITS  2
+#else
+#define CONST_BITS  13
+#define PASS1_BITS  1    /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_298631336  ((INT32)  2446)  /* FIX(0.298631336) */
+#define FIX_0_390180644  ((INT32)  3196)  /* FIX(0.390180644) */
+#define FIX_0_541196100  ((INT32)  4433)  /* FIX(0.541196100) */
+#define FIX_0_765366865  ((INT32)  6270)  /* FIX(0.765366865) */
+#define FIX_0_899976223  ((INT32)  7373)  /* FIX(0.899976223) */
+#define FIX_1_175875602  ((INT32)  9633)  /* FIX(1.175875602) */
+#define FIX_1_501321110  ((INT32)  12299)  /* FIX(1.501321110) */
+#define FIX_1_847759065  ((INT32)  15137)  /* FIX(1.847759065) */
+#define FIX_1_961570560  ((INT32)  16069)  /* FIX(1.961570560) */
+#define FIX_2_053119869  ((INT32)  16819)  /* FIX(2.053119869) */
+#define FIX_2_562915447  ((INT32)  20995)  /* FIX(2.562915447) */
+#define FIX_3_072711026  ((INT32)  25172)  /* FIX(3.072711026) */
+#else
+#define FIX_0_298631336  FIX(0.298631336)
+#define FIX_0_390180644  FIX(0.390180644)
+#define FIX_0_541196100  FIX(0.541196100)
+#define FIX_0_765366865  FIX(0.765366865)
+#define FIX_0_899976223  FIX(0.899976223)
+#define FIX_1_175875602  FIX(1.175875602)
+#define FIX_1_501321110  FIX(1.501321110)
+#define FIX_1_847759065  FIX(1.847759065)
+#define FIX_1_961570560  FIX(1.961570560)
+#define FIX_2_053119869  FIX(2.053119869)
+#define FIX_2_562915447  FIX(2.562915447)
+#define FIX_3_072711026  FIX(3.072711026)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const)  MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const)  ((var) * (const))
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce an int result.  In this module, both inputs and result
+ * are 16 bits or less, so either int or short multiply will work.
+ */
+
+#define DEQUANTIZE(coef,quantval)  (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+     JCOEFPTR coef_block,
+     JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+  INT32 tmp0, tmp1, tmp2, tmp3;
+  INT32 tmp10, tmp11, tmp12, tmp13;
+  INT32 z1, z2, z3, z4, z5;
+  JCOEFPTR inptr;
+  ISLOW_MULT_TYPE * quantptr;
+  int * wsptr;
+  JSAMPROW outptr;
+  JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+  int ctr;
+  int workspace[DCTSIZE2];  /* buffers data between passes */
+  SHIFT_TEMPS
+
+  /* Pass 1: process columns from input, store into work array. */
+  /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+  /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+  inptr = coef_block;
+  quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+  wsptr = workspace;
+  for (ctr = DCTSIZE; ctr > 0; ctr--) {
+    /* Due to quantization, we will usually find that many of the input
+     * coefficients are zero, especially the AC terms.  We can exploit this
+     * by short-circuiting the IDCT calculation for any column in which all
+     * the AC terms are zero.  In that case each output is equal to the
+     * DC coefficient (with scale factor as needed).
+     * With typical images and quantization tables, half or more of the
+     * column DCT calculations can be simplified this way.
+     */
+    
+    if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+  inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+  inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+  inptr[DCTSIZE*7] == 0) {
+      /* AC terms all zero */
+      int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+      
+      wsptr[DCTSIZE*0] = dcval;
+      wsptr[DCTSIZE*1] = dcval;
+      wsptr[DCTSIZE*2] = dcval;
+      wsptr[DCTSIZE*3] = dcval;
+      wsptr[DCTSIZE*4] = dcval;
+      wsptr[DCTSIZE*5] = dcval;
+      wsptr[DCTSIZE*6] = dcval;
+      wsptr[DCTSIZE*7] = dcval;
+      
+      inptr++;      /* advance pointers to next column */
+      quantptr++;
+      wsptr++;
+      continue;
+    }
+    
+    /* Even part: reverse the even part of the forward DCT. */
+    /* The rotator is sqrt(2)*c(-6). */
+    
+    z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+    z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+    
+    z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+    tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+    tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
+    
+    z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+    z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+
+    tmp0 = (z2 + z3) << CONST_BITS;
+    tmp1 = (z2 - z3) << CONST_BITS;
+    
+    tmp10 = tmp0 + tmp3;
+    tmp13 = tmp0 - tmp3;
+    tmp11 = tmp1 + tmp2;
+    tmp12 = tmp1 - tmp2;
+    
+    /* Odd part per figure 8; the matrix is unitary and hence its
+     * transpose is its inverse.  i0..i3 are y7,y5,y3,y1 respectively.
+     */
+    
+    tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+    tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+    tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+    tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+    
+    z1 = tmp0 + tmp3;
+    z2 = tmp1 + tmp2;
+    z3 = tmp0 + tmp2;
+    z4 = tmp1 + tmp3;
+    z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+    
+    tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+    tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+    tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+    tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+    z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+    z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+    z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+    z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+    
+    z3 += z5;
+    z4 += z5;
+    
+    tmp0 += z1 + z3;
+    tmp1 += z2 + z4;
+    tmp2 += z2 + z3;
+    tmp3 += z1 + z4;
+    
+    /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+    
+    wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+    wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+    wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+    wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+    wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+    wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+    wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+    wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+    
+    inptr++;      /* advance pointers to next column */
+    quantptr++;
+    wsptr++;
+  }
+  
+  /* Pass 2: process rows from work array, store into output array. */
+  /* Note that we must descale the results by a factor of 8 == 2**3, */
+  /* and also undo the PASS1_BITS scaling. */
+
+  wsptr = workspace;
+  for (ctr = 0; ctr < DCTSIZE; ctr++) {
+    outptr = output_buf[ctr] + output_col;
+    /* Rows of zeroes can be exploited in the same way as we did with columns.
+     * However, the column calculation has created many nonzero AC terms, so
+     * the simplification applies less often (typically 5% to 10% of the time).
+     * On machines with very fast multiplication, it's possible that the
+     * test takes more time than it's worth.  In that case this section
+     * may be commented out.
+     */
+    
+#ifndef NO_ZERO_ROW_TEST
+    if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
+  wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+      /* AC terms all zero */
+      JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
+          & RANGE_MASK];
+      
+      outptr[0] = dcval;
+      outptr[1] = dcval;
+      outptr[2] = dcval;
+      outptr[3] = dcval;
+      outptr[4] = dcval;
+      outptr[5] = dcval;
+      outptr[6] = dcval;
+      outptr[7] = dcval;
+
+      wsptr += DCTSIZE;    /* advance pointer to next row */
+      continue;
+    }
+#endif
+    
+    /* Even part: reverse the even part of the forward DCT. */
+    /* The rotator is sqrt(2)*c(-6). */
+    
+    z2 = (INT32) wsptr[2];
+    z3 = (INT32) wsptr[6];
+    
+    z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+    tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+    tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
+    
+    tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS;
+    tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS;
+    
+    tmp10 = tmp0 + tmp3;
+    tmp13 = tmp0 - tmp3;
+    tmp11 = tmp1 + tmp2;
+    tmp12 = tmp1 - tmp2;
+    
+    /* Odd part per figure 8; the matrix is unitary and hence its
+     * transpose is its inverse.  i0..i3 are y7,y5,y3,y1 respectively.
+     */
+    
+    tmp0 = (INT32) wsptr[7];
+    tmp1 = (INT32) wsptr[5];
+    tmp2 = (INT32) wsptr[3];
+    tmp3 = (INT32) wsptr[1];
+    
+    z1 = tmp0 + tmp3;
+    z2 = tmp1 + tmp2;
+    z3 = tmp0 + tmp2;
+    z4 = tmp1 + tmp3;
+    z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+    
+    tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+    tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+    tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+    tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+    z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+    z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+    z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+    z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+    
+    z3 += z5;
+    z4 += z5;
+    
+    tmp0 += z1 + z3;
+    tmp1 += z2 + z4;
+    tmp2 += z2 + z3;
+    tmp3 += z1 + z4;
+    
+    /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+    
+    outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3,
+            CONST_BITS+PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3,
+            CONST_BITS+PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2,
+            CONST_BITS+PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2,
+            CONST_BITS+PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1,
+            CONST_BITS+PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1,
+            CONST_BITS+PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0,
+            CONST_BITS+PASS1_BITS+3)
+          & RANGE_MASK];
+    outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0,
+            CONST_BITS+PASS1_BITS+3)
+          & RANGE_MASK];
+    
+    wsptr += DCTSIZE;    /* advance pointer to next row */
+  }
+}
+
+#endif /* DCT_ISLOW_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jidctred.c b/Utilities/ITK/Utilities/itkjpeg/jidctred.c
new file mode 100644
index 0000000000000000000000000000000000000000..5df040c16daeab27505e90d0614546af4a06d698
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jidctred.c
@@ -0,0 +1,398 @@
+/*
+ * jidctred.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains inverse-DCT routines that produce reduced-size output:
+ * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block.
+ *
+ * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M)
+ * algorithm used in jidctint.c.  We simply replace each 8-to-8 1-D IDCT step
+ * with an 8-to-4 step that produces the four averages of two adjacent outputs
+ * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output).
+ * These steps were derived by computing the corresponding values at the end
+ * of the normal LL&M code, then simplifying as much as possible.
+ *
+ * 1x1 is trivial: just take the DC coefficient divided by 8.
+ *
+ * See jidctint.c for additional comments.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h"    /* Private declarations for DCT subsystem */
+
+#ifdef IDCT_SCALING_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+  Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling is the same as in jidctint.c. */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS  13
+#define PASS1_BITS  2
+#else
+#define CONST_BITS  13
+#define PASS1_BITS  1    /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_211164243  ((INT32)  1730)  /* FIX(0.211164243) */
+#define FIX_0_509795579  ((INT32)  4176)  /* FIX(0.509795579) */
+#define FIX_0_601344887  ((INT32)  4926)  /* FIX(0.601344887) */
+#define FIX_0_720959822  ((INT32)  5906)  /* FIX(0.720959822) */
+#define FIX_0_765366865  ((INT32)  6270)  /* FIX(0.765366865) */
+#define FIX_0_850430095  ((INT32)  6967)  /* FIX(0.850430095) */
+#define FIX_0_899976223  ((INT32)  7373)  /* FIX(0.899976223) */
+#define FIX_1_061594337  ((INT32)  8697)  /* FIX(1.061594337) */
+#define FIX_1_272758580  ((INT32)  10426)  /* FIX(1.272758580) */
+#define FIX_1_451774981  ((INT32)  11893)  /* FIX(1.451774981) */
+#define FIX_1_847759065  ((INT32)  15137)  /* FIX(1.847759065) */
+#define FIX_2_172734803  ((INT32)  17799)  /* FIX(2.172734803) */
+#define FIX_2_562915447  ((INT32)  20995)  /* FIX(2.562915447) */
+#define FIX_3_624509785  ((INT32)  29692)  /* FIX(3.624509785) */
+#else
+#define FIX_0_211164243  FIX(0.211164243)
+#define FIX_0_509795579  FIX(0.509795579)
+#define FIX_0_601344887  FIX(0.601344887)
+#define FIX_0_720959822  FIX(0.720959822)
+#define FIX_0_765366865  FIX(0.765366865)
+#define FIX_0_850430095  FIX(0.850430095)
+#define FIX_0_899976223  FIX(0.899976223)
+#define FIX_1_061594337  FIX(1.061594337)
+#define FIX_1_272758580  FIX(1.272758580)
+#define FIX_1_451774981  FIX(1.451774981)
+#define FIX_1_847759065  FIX(1.847759065)
+#define FIX_2_172734803  FIX(2.172734803)
+#define FIX_2_562915447  FIX(2.562915447)
+#define FIX_3_624509785  FIX(3.624509785)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const)  MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const)  ((var) * (const))
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce an int result.  In this module, both inputs and result
+ * are 16 bits or less, so either int or short multiply will work.
+ */
+
+#define DEQUANTIZE(coef,quantval)  (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 4x4 output block.
+ */
+
+GLOBAL(void)
+jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+         JCOEFPTR coef_block,
+         JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+  INT32 tmp0, tmp2, tmp10, tmp12;
+  INT32 z1, z2, z3, z4;
+  JCOEFPTR inptr;
+  ISLOW_MULT_TYPE * quantptr;
+  int * wsptr;
+  JSAMPROW outptr;
+  JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+  int ctr;
+  int workspace[DCTSIZE*4];  /* buffers data between passes */
+  SHIFT_TEMPS
+
+  /* Pass 1: process columns from input, store into work array. */
+
+  inptr = coef_block;
+  quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+  wsptr = workspace;
+  for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
+    /* Don't bother to process column 4, because second pass won't use it */
+    if (ctr == DCTSIZE-4)
+      continue;
+    if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+  inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 &&
+  inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) {
+      /* AC terms all zero; we need not examine term 4 for 4x4 output */
+      int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+      
+      wsptr[DCTSIZE*0] = dcval;
+      wsptr[DCTSIZE*1] = dcval;
+      wsptr[DCTSIZE*2] = dcval;
+      wsptr[DCTSIZE*3] = dcval;
+      
+      continue;
+    }
+    
+    /* Even part */
+    
+    tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+    tmp0 <<= (CONST_BITS+1);
+    
+    z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+    z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+    tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865);
+    
+    tmp10 = tmp0 + tmp2;
+    tmp12 = tmp0 - tmp2;
+    
+    /* Odd part */
+    
+    z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+    z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+    z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+    z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+    
+    tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
+   + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
+   + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
+   + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
+    
+    tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
+   + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
+   + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
+   + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
+
+    /* Final output stage */
+    
+    wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1);
+    wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1);
+    wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1);
+    wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1);
+  }
+  
+  /* Pass 2: process 4 rows from work array, store into output array. */
+
+  wsptr = workspace;
+  for (ctr = 0; ctr < 4; ctr++) {
+    outptr = output_buf[ctr] + output_col;
+    /* It's not clear whether a zero row test is worthwhile here ... */
+
+#ifndef NO_ZERO_ROW_TEST
+    if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 &&
+  wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+      /* AC terms all zero */
+      JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
+          & RANGE_MASK];
+      
+      outptr[0] = dcval;
+      outptr[1] = dcval;
+      outptr[2] = dcval;
+      outptr[3] = dcval;
+      
+      wsptr += DCTSIZE;    /* advance pointer to next row */
+      continue;
+    }
+#endif
+    
+    /* Even part */
+    
+    tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1);
+    
+    tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065)
+   + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865);
+    
+    tmp10 = tmp0 + tmp2;
+    tmp12 = tmp0 - tmp2;
+    
+    /* Odd part */
+    
+    z1 = (INT32) wsptr[7];
+    z2 = (INT32) wsptr[5];
+    z3 = (INT32) wsptr[3];
+    z4 = (INT32) wsptr[1];
+    
+    tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
+   + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
+   + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
+   + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
+    
+    tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
+   + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
+   + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
+   + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
+
+    /* Final output stage */
+    
+    outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2,
+            CONST_BITS+PASS1_BITS+3+1)
+          & RANGE_MASK];
+    outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2,
+            CONST_BITS+PASS1_BITS+3+1)
+          & RANGE_MASK];
+    outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0,
+            CONST_BITS+PASS1_BITS+3+1)
+          & RANGE_MASK];
+    outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0,
+            CONST_BITS+PASS1_BITS+3+1)
+          & RANGE_MASK];
+    
+    wsptr += DCTSIZE;    /* advance pointer to next row */
+  }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 2x2 output block.
+ */
+
+GLOBAL(void)
+jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+         JCOEFPTR coef_block,
+         JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+  INT32 tmp0, tmp10, z1;
+  JCOEFPTR inptr;
+  ISLOW_MULT_TYPE * quantptr;
+  int * wsptr;
+  JSAMPROW outptr;
+  JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+  int ctr;
+  int workspace[DCTSIZE*2];  /* buffers data between passes */
+  SHIFT_TEMPS
+
+  /* Pass 1: process columns from input, store into work array. */
+
+  inptr = coef_block;
+  quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+  wsptr = workspace;
+  for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
+    /* Don't bother to process columns 2,4,6 */
+    if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6)
+      continue;
+    if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 &&
+  inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) {
+      /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */
+      int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+      
+      wsptr[DCTSIZE*0] = dcval;
+      wsptr[DCTSIZE*1] = dcval;
+      
+      continue;
+    }
+    
+    /* Even part */
+    
+    z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+    tmp10 = z1 << (CONST_BITS+2);
+    
+    /* Odd part */
+
+    z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+    tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */
+    z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+    tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */
+    z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+    tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */
+    z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+    tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
+
+    /* Final output stage */
+    
+    wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2);
+    wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2);
+  }
+  
+  /* Pass 2: process 2 rows from work array, store into output array. */
+
+  wsptr = workspace;
+  for (ctr = 0; ctr < 2; ctr++) {
+    outptr = output_buf[ctr] + output_col;
+    /* It's not clear whether a zero row test is worthwhile here ... */
+
+#ifndef NO_ZERO_ROW_TEST
+    if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) {
+      /* AC terms all zero */
+      JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
+          & RANGE_MASK];
+      
+      outptr[0] = dcval;
+      outptr[1] = dcval;
+      
+      wsptr += DCTSIZE;    /* advance pointer to next row */
+      continue;
+    }
+#endif
+    
+    /* Even part */
+    
+    tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2);
+    
+    /* Odd part */
+
+    tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */
+   + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */
+   + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */
+   + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
+
+    /* Final output stage */
+    
+    outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0,
+            CONST_BITS+PASS1_BITS+3+2)
+          & RANGE_MASK];
+    outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0,
+            CONST_BITS+PASS1_BITS+3+2)
+          & RANGE_MASK];
+    
+    wsptr += DCTSIZE;    /* advance pointer to next row */
+  }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 1x1 output block.
+ */
+
+GLOBAL(void)
+jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+         JCOEFPTR coef_block,
+         JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+  int dcval;
+  ISLOW_MULT_TYPE * quantptr;
+  JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+  SHIFT_TEMPS
+
+  /* We hardly need an inverse DCT routine for this: just take the
+   * average pixel value, which is one-eighth of the DC coefficient.
+   */
+  quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+  dcval = DEQUANTIZE(coef_block[0], quantptr[0]);
+  dcval = (int) DESCALE((INT32) dcval, 3);
+
+  output_buf[0][output_col] = range_limit[dcval & RANGE_MASK];
+}
+
+#endif /* IDCT_SCALING_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jinclude.h b/Utilities/ITK/Utilities/itkjpeg/jinclude.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d554f373c6782b53840aa572b27221ef008fb80
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jinclude.h
@@ -0,0 +1,91 @@
+/*
+ * jinclude.h
+ *
+ * Copyright (C) 1991-1994, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file exists to provide a single place to fix any problems with
+ * including the wrong system include files.  (Common problems are taken
+ * care of by the standard jconfig symbols, but on really weird systems
+ * you may have to edit this file.)
+ *
+ * NOTE: this file is NOT intended to be included by applications using the
+ * JPEG library.  Most applications need only include jpeglib.h.
+ */
+
+
+/* Include auto-config file to find out which system include files we need. */
+
+#include "jconfig.h"    /* auto configuration options */
+#define JCONFIG_INCLUDED  /* so that jpeglib.h doesn't do it again */
+
+/*
+ * We need the NULL macro and size_t typedef.
+ * On an ANSI-conforming system it is sufficient to include <stddef.h>.
+ * Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
+ * pull in <sys/types.h> as well.
+ * Note that the core JPEG library does not require <stdio.h>;
+ * only the default error handler and data source/destination modules do.
+ * But we must pull it in because of the references to FILE in jpeglib.h.
+ * You can remove those references if you want to compile without <stdio.h>.
+ */
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+
+/*
+ * We need memory copying and zeroing functions, plus strncpy().
+ * ANSI and System V implementations declare these in <string.h>.
+ * BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
+ * Some systems may declare memset and memcpy in <memory.h>.
+ *
+ * NOTE: we assume the size parameters to these functions are of type size_t.
+ * Change the casts in these macros if not!
+ */
+
+#ifdef NEED_BSD_STRINGS
+
+#include <strings.h>
+#define MEMZERO(target,size)  bzero((void *)(target), (size_t)(size))
+#define MEMCOPY(dest,src,size)  bcopy((const void *)(src), (void *)(dest), (size_t)(size))
+
+#else /* not BSD, assume ANSI/SysV string lib */
+
+#include <string.h>
+#define MEMZERO(target,size)  memset((void *)(target), 0, (size_t)(size))
+#define MEMCOPY(dest,src,size)  memcpy((void *)(dest), (const void *)(src), (size_t)(size))
+
+#endif
+
+/*
+ * In ANSI C, and indeed any rational implementation, size_t is also the
+ * type returned by sizeof().  However, it seems there are some irrational
+ * implementations out there, in which sizeof() returns an int even though
+ * size_t is defined as long or unsigned long.  To ensure consistent results
+ * we always use this SIZEOF() macro in place of using sizeof() directly.
+ */
+
+#define SIZEOF(object)  ((size_t) sizeof(object))
+
+/*
+ * The modules that use fread() and fwrite() always invoke them through
+ * these macros.  On some systems you may need to twiddle the argument casts.
+ * CAUTION: argument order is different from underlying functions!
+ */
+
+#define JFREAD(file,buf,sizeofbuf)  \
+  ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
+#define JFWRITE(file,buf,sizeofbuf)  \
+  ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
diff --git a/Utilities/ITK/Utilities/itkjpeg/jlossls.h b/Utilities/ITK/Utilities/itkjpeg/jlossls.h
new file mode 100644
index 0000000000000000000000000000000000000000..2feccd6d73f850b98d36a32196b74db0cc752d1f
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jlossls.h
@@ -0,0 +1,151 @@
+/*
+ * jlossls.h
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file contains common declarations for the lossless JPEG
+ * codec modules.
+ */
+
+#ifndef JLOSSLS_H
+#define JLOSSLS_H
+
+
+/*
+ * Table H.1: Predictors for lossless coding.
+ */
+
+#define PREDICTOR1  Ra
+#define PREDICTOR2  Rb
+#define PREDICTOR3  Rc
+#define PREDICTOR4  (int) ((INT32) Ra + (INT32) Rb - (INT32) Rc)
+#define PREDICTOR5  (int) ((INT32) Ra + RIGHT_SHIFT((INT32) Rb - (INT32) Rc, 1))
+#define PREDICTOR6  (int) ((INT32) Rb + RIGHT_SHIFT((INT32) Ra - (INT32) Rc, 1))
+#define PREDICTOR7  (int) RIGHT_SHIFT((INT32) Ra + (INT32) Rb, 1)
+
+
+typedef JMETHOD(void, predict_difference_method_ptr,
+    (j_compress_ptr cinfo, int ci,
+     JSAMPROW input_buf, JSAMPROW prev_row,
+     JDIFFROW diff_buf, JDIMENSION width));
+
+typedef JMETHOD(void, scaler_method_ptr,
+    (j_compress_ptr cinfo, int ci,
+     JSAMPROW input_buf, JSAMPROW output_buf,
+     JDIMENSION width));
+
+/* Lossless-specific compression codec (compressor proper) */
+typedef struct {
+  struct jpeg_c_codec pub; /* public fields */
+
+
+  /* Difference buffer control */
+  JMETHOD(void, diff_start_pass, (j_compress_ptr cinfo,
+          J_BUF_MODE pass_mode));
+
+  /* Pointer to data which is private to diff controller */
+  void *diff_private;
+
+
+  /* Entropy encoding */
+  JMETHOD(JDIMENSION, entropy_encode_mcus, (j_compress_ptr cinfo,
+              JDIFFIMAGE diff_buf,
+              JDIMENSION MCU_row_num,
+              JDIMENSION MCU_col_num,
+              JDIMENSION nMCU));
+
+  /* Pointer to data which is private to entropy module */
+  void *entropy_private;
+
+
+  /* Prediction, differencing */
+  JMETHOD(void, predict_start_pass, (j_compress_ptr cinfo));
+
+  /* It is useful to allow each component to have a separate diff method. */
+  predict_difference_method_ptr predict_difference[MAX_COMPONENTS];
+
+  /* Pointer to data which is private to predictor module */
+  void *pred_private;
+
+  /* Sample scaling */
+  JMETHOD(void, scaler_start_pass, (j_compress_ptr cinfo));
+  JMETHOD(void, scaler_scale, (j_compress_ptr cinfo,
+             JSAMPROW input_buf, JSAMPROW output_buf,
+             JDIMENSION width));
+
+  /* Pointer to data which is private to scaler module */
+  void *scaler_private;
+
+} jpeg_lossless_c_codec;
+
+typedef jpeg_lossless_c_codec * j_lossless_c_ptr;
+
+
+typedef JMETHOD(void, predict_undifference_method_ptr,
+    (j_decompress_ptr cinfo, int comp_index,
+     JDIFFROW diff_buf, JDIFFROW prev_row,
+     JDIFFROW undiff_buf, JDIMENSION width));
+
+/* Lossless-specific decompression codec (decompressor proper) */
+typedef struct {
+  struct jpeg_d_codec pub; /* public fields */
+
+
+  /* Difference buffer control */
+  JMETHOD(void, diff_start_input_pass, (j_decompress_ptr cinfo));
+
+  /* Pointer to data which is private to diff controller */
+  void *diff_private;
+
+
+  /* Entropy decoding */
+  JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo));
+  JMETHOD(boolean, entropy_process_restart, (j_decompress_ptr cinfo));
+  JMETHOD(JDIMENSION, entropy_decode_mcus, (j_decompress_ptr cinfo,
+              JDIFFIMAGE diff_buf,
+              JDIMENSION MCU_row_num,
+              JDIMENSION MCU_col_num,
+              JDIMENSION nMCU));
+
+  /* Pointer to data which is private to entropy module */
+  void *entropy_private;
+
+
+  /* Prediction, undifferencing */
+  JMETHOD(void, predict_start_pass, (j_decompress_ptr cinfo));
+  JMETHOD(void, predict_process_restart, (j_decompress_ptr cinfo));
+
+  /* It is useful to allow each component to have a separate undiff method. */
+  predict_undifference_method_ptr predict_undifference[MAX_COMPONENTS];
+
+  /* Pointer to data which is private to predictor module */
+  void *pred_private;
+
+  /* Sample scaling */
+  JMETHOD(void, scaler_start_pass, (j_decompress_ptr cinfo));
+  JMETHOD(void, scaler_scale, (j_decompress_ptr cinfo,
+             JDIFFROW diff_buf, JSAMPROW output_buf,
+             JDIMENSION width));
+
+  /* Pointer to data which is private to scaler module */
+  void *scaler_private;
+
+} jpeg_lossless_d_codec;
+
+typedef jpeg_lossless_d_codec * j_lossless_d_ptr;
+
+
+/* Compression module initialization routines */
+EXTERN(void) jinit_lossless_c_codec JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_lhuff_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_differencer JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_c_scaler JPP((j_compress_ptr cinfo));
+/* Decompression module initialization routines */
+EXTERN(void) jinit_lossless_d_codec JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_lhuff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_undifferencer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_scaler JPP((j_decompress_ptr cinfo));
+
+#endif /* JLOSSLS_H */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jlossy.h b/Utilities/ITK/Utilities/itkjpeg/jlossy.h
new file mode 100644
index 0000000000000000000000000000000000000000..83c43f04ef4cb7191ac9abef316a250331487f5e
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jlossy.h
@@ -0,0 +1,120 @@
+/*
+ * jlossy.h
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file contains common declarations for the lossy (DCT-based)
+ * JPEG codec modules.
+ */
+
+#ifndef JLOSSY_H
+#define JLOSSY_H
+
+
+/* Lossy-specific compression codec (compressor proper) */
+typedef struct {
+  struct jpeg_c_codec pub; /* public fields */
+
+
+  /* Coefficient buffer control */
+  JMETHOD(void, coef_start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+  /*  JMETHOD(boolean, coef_compress_data, (j_compress_ptr cinfo,
+          JSAMPIMAGE input_buf));*/
+
+  /* Pointer to data which is private to coef module */
+  void *coef_private;
+
+
+  /* Forward DCT (also controls coefficient quantization) */
+  JMETHOD(void, fdct_start_pass, (j_compress_ptr cinfo));
+  /* perhaps this should be an array??? */
+  JMETHOD(void, fdct_forward_DCT, (j_compress_ptr cinfo,
+           jpeg_component_info * compptr,
+           JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+           JDIMENSION start_row, JDIMENSION start_col,
+           JDIMENSION num_blocks));
+
+  /* Pointer to data which is private to fdct module */
+  void *fdct_private;
+
+
+  /* Entropy encoding */
+  JMETHOD(boolean, entropy_encode_mcu, (j_compress_ptr cinfo,
+          JBLOCKROW *MCU_data));
+
+  /* Pointer to data which is private to entropy module */
+  void *entropy_private;
+
+} jpeg_lossy_c_codec;
+
+typedef jpeg_lossy_c_codec * j_lossy_c_ptr;
+
+
+
+typedef JMETHOD(void, inverse_DCT_method_ptr,
+    (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+     JCOEFPTR coef_block,
+     JSAMPARRAY output_buf, JDIMENSION output_col));
+
+/* Lossy-specific decompression codec (decompressor proper) */
+typedef struct {
+  struct jpeg_d_codec pub; /* public fields */
+
+
+  /* Coefficient buffer control */
+  JMETHOD(void, coef_start_input_pass, (j_decompress_ptr cinfo));
+  JMETHOD(void, coef_start_output_pass, (j_decompress_ptr cinfo));
+
+  /* Pointer to array of coefficient virtual arrays, or NULL if none */
+  jvirt_barray_ptr *coef_arrays;
+
+  /* Pointer to data which is private to coef module */
+  void *coef_private;
+
+
+  /* Entropy decoding */
+  JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo));
+  JMETHOD(boolean, entropy_decode_mcu, (j_decompress_ptr cinfo,
+          JBLOCKROW *MCU_data));
+
+  /* This is here to share code between baseline and progressive decoders; */
+  /* other modules probably should not use it */
+  boolean entropy_insufficient_data;  /* set TRUE after emitting warning */
+
+  /* Pointer to data which is private to entropy module */
+  void *entropy_private;
+
+
+  /* Inverse DCT (also performs dequantization) */
+  JMETHOD(void, idct_start_pass, (j_decompress_ptr cinfo));
+
+  /* It is useful to allow each component to have a separate IDCT method. */
+  inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
+
+  /* Pointer to data which is private to idct module */
+  void *idct_private;
+
+} jpeg_lossy_d_codec;
+
+typedef jpeg_lossy_d_codec * j_lossy_d_ptr;
+
+
+/* Compression module initialization routines */
+EXTERN(void) jinit_lossy_c_codec JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
+            boolean need_full_buffer));
+EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_shuff_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo));
+
+/* Decompression module initialization routines */
+EXTERN(void) jinit_lossy_d_codec JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
+            boolean need_full_buffer));
+EXTERN(void) jinit_shuff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
+
+#endif /* JLOSSY_H */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jmemmgr.c b/Utilities/ITK/Utilities/itkjpeg/jmemmgr.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e2db9d9e1aea9a006cde91ffacabda8149d0c17
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jmemmgr.c
@@ -0,0 +1,1174 @@
+/*
+ * jmemmgr.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the JPEG system-independent memory management
+ * routines.  This code is usable across a wide variety of machines; most
+ * of the system dependencies have been isolated in a separate file.
+ * The major functions provided here are:
+ *   * pool-based allocation and freeing of memory;
+ *   * policy decisions about how to divide available memory among the
+ *     virtual arrays;
+ *   * control logic for swapping virtual arrays between main memory and
+ *     backing storage.
+ * The separate system-dependent file provides the actual backing-storage
+ * access code, and it contains the policy decision about how much total
+ * main memory to use.
+ * This file is system-dependent in the sense that some of its functions
+ * are unnecessary in some systems.  For example, if there is enough virtual
+ * memory so that backing storage will never be used, much of the virtual
+ * array control logic could be removed.  (Of course, if you have that much
+ * memory then you shouldn't care about a little bit of unused code...)
+ */
+
+#define JPEG_INTERNALS
+#define AM_MEMORY_MANAGER  /* we define jvirt_Xarray_control structs */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h"    /* import the system-dependent declarations */
+
+#ifndef NO_GETENV
+#ifndef HAVE_STDLIB_H    /* <stdlib.h> should declare getenv() */
+extern char * getenv JPP((const char * name));
+#endif
+#endif
+
+
+/*
+ * Some important notes:
+ *   The allocation routines provided here must never return NULL.
+ *   They should exit to error_exit if unsuccessful.
+ *
+ *   It's not a good idea to try to merge the sarray, barray and darray
+ *   routines, even though they are textually almost the same, because
+ *   samples are usually stored as bytes while coefficients and differenced
+ *   are shorts or ints.  Thus, in machines where byte pointers have a
+ *   different representation from word pointers, the resulting machine
+ *   code could not be the same.
+ */
+
+
+/*
+ * Many machines require storage alignment: longs must start on 4-byte
+ * boundaries, doubles on 8-byte boundaries, etc.  On such machines, malloc()
+ * always returns pointers that are multiples of the worst-case alignment
+ * requirement, and we had better do so too.
+ * There isn't any really portable way to determine the worst-case alignment
+ * requirement.  This module assumes that the alignment requirement is
+ * multiples of sizeof(ALIGN_TYPE).
+ * By default, we define ALIGN_TYPE as double.  This is necessary on some
+ * workstations (where doubles really do need 8-byte alignment) and will work
+ * fine on nearly everything.  If your machine has lesser alignment needs,
+ * you can save a few bytes by making ALIGN_TYPE smaller.
+ * The only place I know of where this will NOT work is certain Macintosh
+ * 680x0 compilers that define double as a 10-byte IEEE extended float.
+ * Doing 10-byte alignment is counterproductive because longwords won't be
+ * aligned well.  Put "#define ALIGN_TYPE long" in jconfig.h if you have
+ * such a compiler.
+ */
+
+#ifndef ALIGN_TYPE    /* so can override from jconfig.h */
+#define ALIGN_TYPE  double
+#endif
+
+
+/*
+ * We allocate objects from "pools", where each pool is gotten with a single
+ * request to jpeg_get_small() or jpeg_get_large().  There is no per-object
+ * overhead within a pool, except for alignment padding.  Each pool has a
+ * header with a link to the next pool of the same class.
+ * Small and large pool headers are identical except that the latter's
+ * link pointer must be FAR on 80x86 machines.
+ * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE
+ * field.  This forces the compiler to make SIZEOF(small_pool_hdr) a multiple
+ * of the alignment requirement of ALIGN_TYPE.
+ */
+
+typedef union small_pool_struct * small_pool_ptr;
+
+typedef union small_pool_struct {
+  struct {
+    small_pool_ptr next;  /* next in list of pools */
+    size_t bytes_used;    /* how many bytes already used within pool */
+    size_t bytes_left;    /* bytes still available in this pool */
+  } hdr;
+  ALIGN_TYPE dummy;    /* included in union to ensure alignment */
+} small_pool_hdr;
+
+typedef union large_pool_struct FAR * large_pool_ptr;
+
+typedef union large_pool_struct {
+  struct {
+    large_pool_ptr next;  /* next in list of pools */
+    size_t bytes_used;    /* how many bytes already used within pool */
+    size_t bytes_left;    /* bytes still available in this pool */
+  } hdr;
+  ALIGN_TYPE dummy;    /* included in union to ensure alignment */
+} large_pool_hdr;
+
+
+/*
+ * Here is the full definition of a memory manager object.
+ */
+
+typedef struct {
+  struct jpeg_memory_mgr pub;  /* public fields */
+
+  /* Each pool identifier (lifetime class) names a linked list of pools. */
+  small_pool_ptr small_list[JPOOL_NUMPOOLS];
+  large_pool_ptr large_list[JPOOL_NUMPOOLS];
+
+  /* Since we only have one lifetime class of virtual arrays, only one
+   * linked list is necessary (for each datatype).  Note that the virtual
+   * array control blocks being linked together are actually stored somewhere
+   * in the small-pool list.
+   */
+  jvirt_sarray_ptr virt_sarray_list;
+  jvirt_barray_ptr virt_barray_list;
+
+  /* This counts total space obtained from jpeg_get_small/large */
+  long total_space_allocated;
+
+  /* alloc_sarray and alloc_barray set this value for use by virtual
+   * array routines.
+   */
+  JDIMENSION last_rowsperchunk;  /* from most recent alloc_sarray/barray */
+} my_memory_mgr;
+
+typedef my_memory_mgr * my_mem_ptr;
+
+
+/*
+ * The control blocks for virtual arrays.
+ * Note that these blocks are allocated in the "small" pool area.
+ * System-dependent info for the associated backing store (if any) is hidden
+ * inside the backing_store_info struct.
+ */
+
+struct jvirt_sarray_control {
+  JSAMPARRAY mem_buffer;  /* => the in-memory buffer */
+  JDIMENSION rows_in_array;  /* total virtual array height */
+  JDIMENSION samplesperrow;  /* width of array (and of memory buffer) */
+  JDIMENSION maxaccess;    /* max rows accessed by access_virt_sarray */
+  JDIMENSION rows_in_mem;  /* height of memory buffer */
+  JDIMENSION rowsperchunk;  /* allocation chunk size in mem_buffer */
+  JDIMENSION cur_start_row;  /* first logical row # in the buffer */
+  JDIMENSION first_undef_row;  /* row # of first uninitialized row */
+  boolean pre_zero;    /* pre-zero mode requested? */
+  boolean dirty;    /* do current buffer contents need written? */
+  boolean b_s_open;    /* is backing-store data valid? */
+  jvirt_sarray_ptr next;  /* link to next virtual sarray control block */
+  backing_store_info b_s_info;  /* System-dependent control info */
+};
+
+struct jvirt_barray_control {
+  JBLOCKARRAY mem_buffer;  /* => the in-memory buffer */
+  JDIMENSION rows_in_array;  /* total virtual array height */
+  JDIMENSION blocksperrow;  /* width of array (and of memory buffer) */
+  JDIMENSION maxaccess;    /* max rows accessed by access_virt_barray */
+  JDIMENSION rows_in_mem;  /* height of memory buffer */
+  JDIMENSION rowsperchunk;  /* allocation chunk size in mem_buffer */
+  JDIMENSION cur_start_row;  /* first logical row # in the buffer */
+  JDIMENSION first_undef_row;  /* row # of first uninitialized row */
+  boolean pre_zero;    /* pre-zero mode requested? */
+  boolean dirty;    /* do current buffer contents need written? */
+  boolean b_s_open;    /* is backing-store data valid? */
+  jvirt_barray_ptr next;  /* link to next virtual barray control block */
+  backing_store_info b_s_info;  /* System-dependent control info */
+};
+
+
+#ifdef MEM_STATS    /* optional extra stuff for statistics */
+
+LOCAL(void)
+print_mem_stats (j_common_ptr cinfo, int pool_id)
+{
+  my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+  small_pool_ptr shdr_ptr;
+  large_pool_ptr lhdr_ptr;
+
+  /* Since this is only a debugging stub, we can cheat a little by using
+   * fprintf directly rather than going through the trace message code.
+   * This is helpful because message parm array can't handle longs.
+   */
+  fprintf(stderr, "Freeing pool %d, total space = %ld\n",
+    pool_id, mem->total_space_allocated);
+
+  for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
+       lhdr_ptr = lhdr_ptr->hdr.next) {
+    fprintf(stderr, "  Large chunk used %ld\n",
+      (long) lhdr_ptr->hdr.bytes_used);
+  }
+
+  for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
+       shdr_ptr = shdr_ptr->hdr.next) {
+    fprintf(stderr, "  Small chunk used %ld free %ld\n",
+      (long) shdr_ptr->hdr.bytes_used,
+      (long) shdr_ptr->hdr.bytes_left);
+  }
+}
+
+#endif /* MEM_STATS */
+
+
+LOCAL(void)
+out_of_memory (j_common_ptr cinfo, int which)
+/* Report an out-of-memory error and stop execution */
+/* If we compiled MEM_STATS support, report alloc requests before dying */
+{
+#ifdef MEM_STATS
+  cinfo->err->trace_level = 2;  /* force self_destruct to report stats */
+#endif
+  ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
+}
+
+
+/*
+ * Allocation of "small" objects.
+ *
+ * For these, we use pooled storage.  When a new pool must be created,
+ * we try to get enough space for the current request plus a "slop" factor,
+ * where the slop will be the amount of leftover space in the new pool.
+ * The speed vs. space tradeoff is largely determined by the slop values.
+ * A different slop value is provided for each pool class (lifetime),
+ * and we also distinguish the first pool of a class from later ones.
+ * NOTE: the values given work fairly well on both 16- and 32-bit-int
+ * machines, but may be too small if longs are 64 bits or more.
+ */
+
+static const size_t first_pool_slop[JPOOL_NUMPOOLS] = 
+{
+  1600,      /* first PERMANENT pool */
+  16000      /* first IMAGE pool */
+};
+
+static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = 
+{
+  0,      /* additional PERMANENT pools */
+  5000      /* additional IMAGE pools */
+};
+
+#define MIN_SLOP  50    /* greater than 0 to avoid futile looping */
+
+
+METHODDEF(void *)
+alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+/* Allocate a "small" object */
+{
+  my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+  small_pool_ptr hdr_ptr, prev_hdr_ptr;
+  char * data_ptr;
+  size_t odd_bytes, min_request, slop;
+
+  /* Check for unsatisfiable request (do now to ensure no overflow below) */
+  if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr)))
+    out_of_memory(cinfo, 1);  /* request exceeds malloc's ability */
+
+  /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
+  odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
+  if (odd_bytes > 0)
+    sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
+
+  /* See if space is available in any existing pool */
+  if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+    ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);  /* safety check */
+  prev_hdr_ptr = NULL;
+  hdr_ptr = mem->small_list[pool_id];
+  while (hdr_ptr != NULL) {
+    if (hdr_ptr->hdr.bytes_left >= sizeofobject)
+      break;      /* found pool with enough space */
+    prev_hdr_ptr = hdr_ptr;
+    hdr_ptr = hdr_ptr->hdr.next;
+  }
+
+  /* Time to make a new pool? */
+  if (hdr_ptr == NULL) {
+    /* min_request is what we need now, slop is what will be leftover */
+    min_request = sizeofobject + SIZEOF(small_pool_hdr);
+    if (prev_hdr_ptr == NULL)  /* first pool in class? */
+      slop = first_pool_slop[pool_id];
+    else
+      slop = extra_pool_slop[pool_id];
+    /* Don't ask for more than MAX_ALLOC_CHUNK */
+    if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
+      slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
+    /* Try to get space, if fail reduce slop and try again */
+    for (;;) {
+      hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
+      if (hdr_ptr != NULL)
+  break;
+      slop /= 2;
+      if (slop < MIN_SLOP)  /* give up when it gets real small */
+  out_of_memory(cinfo, 2); /* jpeg_get_small failed */
+    }
+    mem->total_space_allocated += min_request + slop;
+    /* Success, initialize the new pool header and add to end of list */
+    hdr_ptr->hdr.next = NULL;
+    hdr_ptr->hdr.bytes_used = 0;
+    hdr_ptr->hdr.bytes_left = sizeofobject + slop;
+    if (prev_hdr_ptr == NULL)  /* first pool in class? */
+      mem->small_list[pool_id] = hdr_ptr;
+    else
+      prev_hdr_ptr->hdr.next = hdr_ptr;
+  }
+
+  /* OK, allocate the object from the current pool */
+  data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */
+  data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */
+  hdr_ptr->hdr.bytes_used += sizeofobject;
+  hdr_ptr->hdr.bytes_left -= sizeofobject;
+
+  return (void *) data_ptr;
+}
+
+
+/*
+ * Allocation of "large" objects.
+ *
+ * The external semantics of these are the same as "small" objects,
+ * except that FAR pointers are used on 80x86.  However the pool
+ * management heuristics are quite different.  We assume that each
+ * request is large enough that it may as well be passed directly to
+ * jpeg_get_large; the pool management just links everything together
+ * so that we can free it all on demand.
+ * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY
+ * structures.  The routines that create these structures (see below)
+ * deliberately bunch rows together to ensure a large request size.
+ */
+
+METHODDEF(void FAR *)
+alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+/* Allocate a "large" object */
+{
+  my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+  large_pool_ptr hdr_ptr;
+  size_t odd_bytes;
+
+  /* Check for unsatisfiable request (do now to ensure no overflow below) */
+  if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)))
+    out_of_memory(cinfo, 3);  /* request exceeds malloc's ability */
+
+  /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
+  odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
+  if (odd_bytes > 0)
+    sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
+
+  /* Always make a new pool */
+  if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+    ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);  /* safety check */
+
+  hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
+              SIZEOF(large_pool_hdr));
+  if (hdr_ptr == NULL)
+    out_of_memory(cinfo, 4);  /* jpeg_get_large failed */
+  mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr);
+
+  /* Success, initialize the new pool header and add to list */
+  hdr_ptr->hdr.next = mem->large_list[pool_id];
+  /* We maintain space counts in each pool header for statistical purposes,
+   * even though they are not needed for allocation.
+   */
+  hdr_ptr->hdr.bytes_used = sizeofobject;
+  hdr_ptr->hdr.bytes_left = 0;
+  mem->large_list[pool_id] = hdr_ptr;
+
+  return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */
+}
+
+
+/*
+ * Creation of 2-D sample arrays.
+ * The pointers are in near heap, the samples themselves in FAR heap.
+ *
+ * To minimize allocation overhead and to allow I/O of large contiguous
+ * blocks, we allocate the sample rows in groups of as many rows as possible
+ * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request.
+ * NB: the virtual array control routines, later in this file, know about
+ * this chunking of rows.  The rowsperchunk value is left in the mem manager
+ * object so that it can be saved away if this sarray is the workspace for
+ * a virtual array.
+ */
+
+METHODDEF(JSAMPARRAY)
+alloc_sarray (j_common_ptr cinfo, int pool_id,
+        JDIMENSION samplesperrow, JDIMENSION numrows)
+/* Allocate a 2-D sample array */
+{
+  my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+  JSAMPARRAY result;
+  JSAMPROW workspace;
+  JDIMENSION rowsperchunk, currow, i;
+  long ltemp;
+
+  /* Calculate max # of rows allowed in one allocation chunk */
+  ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
+    ((long) samplesperrow * SIZEOF(JSAMPLE));
+  if (ltemp <= 0)
+    ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+  if (ltemp < (long) numrows)
+    rowsperchunk = (JDIMENSION) ltemp;
+  else
+    rowsperchunk = numrows;
+  mem->last_rowsperchunk = rowsperchunk;
+
+  /* Get space for row pointers (small object) */
+  result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
+            (size_t) (numrows * SIZEOF(JSAMPROW)));
+
+  /* Get the rows themselves (large objects) */
+  currow = 0;
+  while (currow < numrows) {
+    rowsperchunk = MIN(rowsperchunk, numrows - currow);
+    workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
+  (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
+      * SIZEOF(JSAMPLE)));
+    for (i = rowsperchunk; i > 0; i--) {
+      result[currow++] = workspace;
+      workspace += samplesperrow;
+    }
+  }
+
+  return result;
+}
+
+
+/*
+ * Creation of 2-D coefficient-block arrays.
+ * This is essentially the same as the code for sample arrays, above.
+ */
+
+METHODDEF(JBLOCKARRAY)
+alloc_barray (j_common_ptr cinfo, int pool_id,
+        JDIMENSION blocksperrow, JDIMENSION numrows)
+/* Allocate a 2-D coefficient-block array */
+{
+  my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+  JBLOCKARRAY result;
+  JBLOCKROW workspace;
+  JDIMENSION rowsperchunk, currow, i;
+  long ltemp;
+
+  /* Calculate max # of rows allowed in one allocation chunk */
+  ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
+    ((long) blocksperrow * SIZEOF(JBLOCK));
+  if (ltemp <= 0)
+    ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+  if (ltemp < (long) numrows)
+    rowsperchunk = (JDIMENSION) ltemp;
+  else
+    rowsperchunk = numrows;
+  mem->last_rowsperchunk = rowsperchunk;
+
+  /* Get space for row pointers (small object) */
+  result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
+             (size_t) (numrows * SIZEOF(JBLOCKROW)));
+
+  /* Get the rows themselves (large objects) */
+  currow = 0;
+  while (currow < numrows) {
+    rowsperchunk = MIN(rowsperchunk, numrows - currow);
+    workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
+  (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
+      * SIZEOF(JBLOCK)));
+    for (i = rowsperchunk; i > 0; i--) {
+      result[currow++] = workspace;
+      workspace += blocksperrow;
+    }
+  }
+
+  return result;
+}
+
+
+#ifdef NEED_DARRAY
+
+/*
+ * Creation of 2-D difference arrays.
+ * This is essentially the same as the code for sample arrays, above.
+ */
+
+METHODDEF(JDIFFARRAY)
+alloc_darray (j_common_ptr cinfo, int pool_id,
+        JDIMENSION diffsperrow, JDIMENSION numrows)
+/* Allocate a 2-D difference array */
+{
+  my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+  JDIFFARRAY result;
+  JDIFFROW workspace;
+  JDIMENSION rowsperchunk, currow, i;
+  long ltemp;
+
+  /* Calculate max # of rows allowed in one allocation chunk */
+  ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
+    ((long) diffsperrow * SIZEOF(JDIFF));
+  if (ltemp <= 0)
+    ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+  if (ltemp < (long) numrows)
+    rowsperchunk = (JDIMENSION) ltemp;
+  else
+    rowsperchunk = numrows;
+  mem->last_rowsperchunk = rowsperchunk;
+
+  /* Get space for row pointers (small object) */
+  result = (JDIFFARRAY) alloc_small(cinfo, pool_id,
+            (size_t) (numrows * SIZEOF(JDIFFROW)));
+
+  /* Get the rows themselves (large objects) */
+  currow = 0;
+  while (currow < numrows) {
+    rowsperchunk = MIN(rowsperchunk, numrows - currow);
+    workspace = (JDIFFROW) alloc_large(cinfo, pool_id,
+  (size_t) ((size_t) rowsperchunk * (size_t) diffsperrow
+      * SIZEOF(JDIFF)));
+    for (i = rowsperchunk; i > 0; i--) {
+      result[currow++] = workspace;
+      workspace += diffsperrow;
+    }
+  }
+
+  return result;
+}
+
+#endif
+
+
+/*
+ * About virtual array management:
+ *
+ * The above "normal" array routines are only used to allocate strip buffers
+ * (as wide as the image, but just a few rows high).  Full-image-sized buffers
+ * are handled as "virtual" arrays.  The array is still accessed a strip at a
+ * time, but the memory manager must save the whole array for repeated
+ * accesses.  The intended implementation is that there is a strip buffer in
+ * memory (as high as is possible given the desired memory limit), plus a
+ * backing file that holds the rest of the array.
+ *
+ * The request_virt_array routines are told the total size of the image and
+ * the maximum number of rows that will be accessed at once.  The in-memory
+ * buffer must be at least as large as the maxaccess value.
+ *
+ * The request routines create control blocks but not the in-memory buffers.
+ * That is postponed until realize_virt_arrays is called.  At that time the
+ * total amount of space needed is known (approximately, anyway), so free
+ * memory can be divided up fairly.
+ *
+ * The access_virt_array routines are responsible for making a specific strip
+ * area accessible (after reading or writing the backing file, if necessary).
+ * Note that the access routines are told whether the caller intends to modify
+ * the accessed strip; during a read-only pass this saves having to rewrite
+ * data to disk.  The access routines are also responsible for pre-zeroing
+ * any newly accessed rows, if pre-zeroing was requested.
+ *
+ * In current usage, the access requests are usually for nonoverlapping
+ * strips; that is, successive access start_row numbers differ by exactly
+ * num_rows = maxaccess.  This means we can get good performance with simple
+ * buffer dump/reload logic, by making the in-memory buffer be a multiple
+ * of the access height; then there will never be accesses across bufferload
+ * boundaries.  The code will still work with overlapping access requests,
+ * but it doesn't handle bufferload overlaps very efficiently.
+ */
+
+
+METHODDEF(jvirt_sarray_ptr)
+request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
+         JDIMENSION samplesperrow, JDIMENSION numrows,
+         JDIMENSION maxaccess)
+/* Request a virtual 2-D sample array */
+{
+  my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+  jvirt_sarray_ptr result;
+
+  /* Only IMAGE-lifetime virtual arrays are currently supported */
+  if (pool_id != JPOOL_IMAGE)
+    ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);  /* safety check */
+
+  /* get control block */
+  result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
+            SIZEOF(struct jvirt_sarray_control));
+
+  result->mem_buffer = NULL;  /* marks array not yet realized */
+  result->rows_in_array = numrows;
+  result->samplesperrow = samplesperrow;
+  result->maxaccess = maxaccess;
+  result->pre_zero = pre_zero;
+  result->b_s_open = FALSE;  /* no associated backing-store object */
+  result->next = mem->virt_sarray_list; /* add to list of virtual arrays */
+  mem->virt_sarray_list = result;
+
+  return result;
+}
+
+
+METHODDEF(jvirt_barray_ptr)
+request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
+         JDIMENSION blocksperrow, JDIMENSION numrows,
+         JDIMENSION maxaccess)
+/* Request a virtual 2-D coefficient-block array */
+{
+  my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+  jvirt_barray_ptr result;
+
+  /* Only IMAGE-lifetime virtual arrays are currently supported */
+  if (pool_id != JPOOL_IMAGE)
+    ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);  /* safety check */
+
+  /* get control block */
+  result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
+            SIZEOF(struct jvirt_barray_control));
+
+  result->mem_buffer = NULL;  /* marks array not yet realized */
+  result->rows_in_array = numrows;
+  result->blocksperrow = blocksperrow;
+  result->maxaccess = maxaccess;
+  result->pre_zero = pre_zero;
+  result->b_s_open = FALSE;  /* no associated backing-store object */
+  result->next = mem->virt_barray_list; /* add to list of virtual arrays */
+  mem->virt_barray_list = result;
+
+  return result;
+}
+
+
+METHODDEF(void)
+realize_virt_arrays (j_common_ptr cinfo)
+/* Allocate the in-memory buffers for any unrealized virtual arrays */
+{
+  my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+  long space_per_minheight, maximum_space, avail_mem;
+  long minheights, max_minheights;
+  jvirt_sarray_ptr sptr;
+  jvirt_barray_ptr bptr;
+
+  /* Compute the minimum space needed (maxaccess rows in each buffer)
+   * and the maximum space needed (full image height in each buffer).
+   * These may be of use to the system-dependent jpeg_mem_available routine.
+   */
+  space_per_minheight = 0;
+  maximum_space = 0;
+  for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+    if (sptr->mem_buffer == NULL) { /* if not realized yet */
+      space_per_minheight += (long) sptr->maxaccess *
+           (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
+      maximum_space += (long) sptr->rows_in_array *
+           (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
+    }
+  }
+  for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+    if (bptr->mem_buffer == NULL) { /* if not realized yet */
+      space_per_minheight += (long) bptr->maxaccess *
+           (long) bptr->blocksperrow * SIZEOF(JBLOCK);
+      maximum_space += (long) bptr->rows_in_array *
+           (long) bptr->blocksperrow * SIZEOF(JBLOCK);
+    }
+  }
+
+  if (space_per_minheight <= 0)
+    return;      /* no unrealized arrays, no work */
+
+  /* Determine amount of memory to actually use; this is system-dependent. */
+  avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space,
+         mem->total_space_allocated);
+
+  /* If the maximum space needed is available, make all the buffers full
+   * height; otherwise parcel it out with the same number of minheights
+   * in each buffer.
+   */
+  if (avail_mem >= maximum_space)
+    max_minheights = 1000000000L;
+  else {
+    max_minheights = avail_mem / space_per_minheight;
+    /* If there doesn't seem to be enough space, try to get the minimum
+     * anyway.  This allows a "stub" implementation of jpeg_mem_available().
+     */
+    if (max_minheights <= 0)
+      max_minheights = 1;
+  }
+
+  /* Allocate the in-memory buffers and initialize backing store as needed. */
+
+  for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+    if (sptr->mem_buffer == NULL) { /* if not realized yet */
+      minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
+      if (minheights <= max_minheights) {
+  /* This buffer fits in memory */
+  sptr->rows_in_mem = sptr->rows_in_array;
+      } else {
+  /* It doesn't fit in memory, create backing store. */
+  sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
+  jpeg_open_backing_store(cinfo, & sptr->b_s_info,
+        (long) sptr->rows_in_array *
+        (long) sptr->samplesperrow *
+        (long) SIZEOF(JSAMPLE));
+  sptr->b_s_open = TRUE;
+      }
+      sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
+              sptr->samplesperrow, sptr->rows_in_mem);
+      sptr->rowsperchunk = mem->last_rowsperchunk;
+      sptr->cur_start_row = 0;
+      sptr->first_undef_row = 0;
+      sptr->dirty = FALSE;
+    }
+  }
+
+  for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+    if (bptr->mem_buffer == NULL) { /* if not realized yet */
+      minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
+      if (minheights <= max_minheights) {
+  /* This buffer fits in memory */
+  bptr->rows_in_mem = bptr->rows_in_array;
+      } else {
+  /* It doesn't fit in memory, create backing store. */
+  bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
+  jpeg_open_backing_store(cinfo, & bptr->b_s_info,
+        (long) bptr->rows_in_array *
+        (long) bptr->blocksperrow *
+        (long) SIZEOF(JBLOCK));
+  bptr->b_s_open = TRUE;
+      }
+      bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
+              bptr->blocksperrow, bptr->rows_in_mem);
+      bptr->rowsperchunk = mem->last_rowsperchunk;
+      bptr->cur_start_row = 0;
+      bptr->first_undef_row = 0;
+      bptr->dirty = FALSE;
+    }
+  }
+}
+
+
+LOCAL(void)
+do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
+/* Do backing store read or write of a virtual sample array */
+{
+  long bytesperrow, file_offset, byte_count, rows, thisrow, i;
+
+  bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE);
+  file_offset = ptr->cur_start_row * bytesperrow;
+  /* Loop to read or write each allocation chunk in mem_buffer */
+  for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+    /* One chunk, but check for short chunk at end of buffer */
+    rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+    /* Transfer no more than is currently defined */
+    thisrow = (long) ptr->cur_start_row + i;
+    rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+    /* Transfer no more than fits in file */
+    rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+    if (rows <= 0)    /* this chunk might be past end of file! */
+      break;
+    byte_count = rows * bytesperrow;
+    if (writing)
+      (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
+              (void FAR *) ptr->mem_buffer[i],
+              file_offset, byte_count);
+    else
+      (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
+             (void FAR *) ptr->mem_buffer[i],
+             file_offset, byte_count);
+    file_offset += byte_count;
+  }
+}
+
+
+LOCAL(void)
+do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
+/* Do backing store read or write of a virtual coefficient-block array */
+{
+  long bytesperrow, file_offset, byte_count, rows, thisrow, i;
+
+  bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK);
+  file_offset = ptr->cur_start_row * bytesperrow;
+  /* Loop to read or write each allocation chunk in mem_buffer */
+  for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+    /* One chunk, but check for short chunk at end of buffer */
+    rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+    /* Transfer no more than is currently defined */
+    thisrow = (long) ptr->cur_start_row + i;
+    rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+    /* Transfer no more than fits in file */
+    rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+    if (rows <= 0)    /* this chunk might be past end of file! */
+      break;
+    byte_count = rows * bytesperrow;
+    if (writing)
+      (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
+              (void FAR *) ptr->mem_buffer[i],
+              file_offset, byte_count);
+    else
+      (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
+             (void FAR *) ptr->mem_buffer[i],
+             file_offset, byte_count);
+    file_offset += byte_count;
+  }
+}
+
+
+METHODDEF(JSAMPARRAY)
+access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
+        JDIMENSION start_row, JDIMENSION num_rows,
+        boolean writable)
+/* Access the part of a virtual sample array starting at start_row */
+/* and extending for num_rows rows.  writable is true if  */
+/* caller intends to modify the accessed area. */
+{
+  JDIMENSION end_row = start_row + num_rows;
+  JDIMENSION undef_row;
+
+  /* debugging check */
+  if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
+      ptr->mem_buffer == NULL)
+    ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+
+  /* Make the desired part of the virtual array accessible */
+  if (start_row < ptr->cur_start_row ||
+      end_row > ptr->cur_start_row+ptr->rows_in_mem) {
+    if (! ptr->b_s_open)
+      ERREXIT(cinfo, JERR_VIRTUAL_BUG);
+    /* Flush old buffer contents if necessary */
+    if (ptr->dirty) {
+      do_sarray_io(cinfo, ptr, TRUE);
+      ptr->dirty = FALSE;
+    }
+    /* Decide what part of virtual array to access.
+     * Algorithm: if target address > current window, assume forward scan,
+     * load starting at target address.  If target address < current window,
+     * assume backward scan, load so that target area is top of window.
+     * Note that when switching from forward write to forward read, will have
+     * start_row = 0, so the limiting case applies and we load from 0 anyway.
+     */
+    if (start_row > ptr->cur_start_row) {
+      ptr->cur_start_row = start_row;
+    } else {
+      /* use long arithmetic here to avoid overflow & unsigned problems */
+      long ltemp;
+
+      ltemp = (long) end_row - (long) ptr->rows_in_mem;
+      if (ltemp < 0)
+  ltemp = 0;    /* don't fall off front end of file */
+      ptr->cur_start_row = (JDIMENSION) ltemp;
+    }
+    /* Read in the selected part of the array.
+     * During the initial write pass, we will do no actual read
+     * because the selected part is all undefined.
+     */
+    do_sarray_io(cinfo, ptr, FALSE);
+  }
+  /* Ensure the accessed part of the array is defined; prezero if needed.
+   * To improve locality of access, we only prezero the part of the array
+   * that the caller is about to access, not the entire in-memory array.
+   */
+  if (ptr->first_undef_row < end_row) {
+    if (ptr->first_undef_row < start_row) {
+      if (writable)    /* writer skipped over a section of array */
+  ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+      undef_row = start_row;  /* but reader is allowed to read ahead */
+    } else {
+      undef_row = ptr->first_undef_row;
+    }
+    if (writable)
+      ptr->first_undef_row = end_row;
+    if (ptr->pre_zero) {
+      size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
+      undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
+      end_row -= ptr->cur_start_row;
+      while (undef_row < end_row) {
+  jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
+  undef_row++;
+      }
+    } else {
+      if (! writable)    /* reader looking at undefined data */
+  ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+    }
+  }
+  /* Flag the buffer dirty if caller will write in it */
+  if (writable)
+    ptr->dirty = TRUE;
+  /* Return address of proper part of the buffer */
+  return ptr->mem_buffer + (start_row - ptr->cur_start_row);
+}
+
+
+METHODDEF(JBLOCKARRAY)
+access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
+        JDIMENSION start_row, JDIMENSION num_rows,
+        boolean writable)
+/* Access the part of a virtual block array starting at start_row */
+/* and extending for num_rows rows.  writable is true if  */
+/* caller intends to modify the accessed area. */
+{
+  JDIMENSION end_row = start_row + num_rows;
+  JDIMENSION undef_row;
+
+  /* debugging check */
+  if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
+      ptr->mem_buffer == NULL)
+    ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+
+  /* Make the desired part of the virtual array accessible */
+  if (start_row < ptr->cur_start_row ||
+      end_row > ptr->cur_start_row+ptr->rows_in_mem) {
+    if (! ptr->b_s_open)
+      ERREXIT(cinfo, JERR_VIRTUAL_BUG);
+    /* Flush old buffer contents if necessary */
+    if (ptr->dirty) {
+      do_barray_io(cinfo, ptr, TRUE);
+      ptr->dirty = FALSE;
+    }
+    /* Decide what part of virtual array to access.
+     * Algorithm: if target address > current window, assume forward scan,
+     * load starting at target address.  If target address < current window,
+     * assume backward scan, load so that target area is top of window.
+     * Note that when switching from forward write to forward read, will have
+     * start_row = 0, so the limiting case applies and we load from 0 anyway.
+     */
+    if (start_row > ptr->cur_start_row) {
+      ptr->cur_start_row = start_row;
+    } else {
+      /* use long arithmetic here to avoid overflow & unsigned problems */
+      long ltemp;
+
+      ltemp = (long) end_row - (long) ptr->rows_in_mem;
+      if (ltemp < 0)
+  ltemp = 0;    /* don't fall off front end of file */
+      ptr->cur_start_row = (JDIMENSION) ltemp;
+    }
+    /* Read in the selected part of the array.
+     * During the initial write pass, we will do no actual read
+     * because the selected part is all undefined.
+     */
+    do_barray_io(cinfo, ptr, FALSE);
+  }
+  /* Ensure the accessed part of the array is defined; prezero if needed.
+   * To improve locality of access, we only prezero the part of the array
+   * that the caller is about to access, not the entire in-memory array.
+   */
+  if (ptr->first_undef_row < end_row) {
+    if (ptr->first_undef_row < start_row) {
+      if (writable)    /* writer skipped over a section of array */
+  ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+      undef_row = start_row;  /* but reader is allowed to read ahead */
+    } else {
+      undef_row = ptr->first_undef_row;
+    }
+    if (writable)
+      ptr->first_undef_row = end_row;
+    if (ptr->pre_zero) {
+      size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
+      undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
+      end_row -= ptr->cur_start_row;
+      while (undef_row < end_row) {
+  jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
+  undef_row++;
+      }
+    } else {
+      if (! writable)    /* reader looking at undefined data */
+  ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+    }
+  }
+  /* Flag the buffer dirty if caller will write in it */
+  if (writable)
+    ptr->dirty = TRUE;
+  /* Return address of proper part of the buffer */
+  return ptr->mem_buffer + (start_row - ptr->cur_start_row);
+}
+
+
+/*
+ * Release all objects belonging to a specified pool.
+ */
+
+METHODDEF(void)
+free_pool (j_common_ptr cinfo, int pool_id)
+{
+  my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+  small_pool_ptr shdr_ptr;
+  large_pool_ptr lhdr_ptr;
+  size_t space_freed;
+
+  if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+    ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id);  /* safety check */
+
+#ifdef MEM_STATS
+  if (cinfo->err->trace_level > 1)
+    print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */
+#endif
+
+  /* If freeing IMAGE pool, close any virtual arrays first */
+  if (pool_id == JPOOL_IMAGE) {
+    jvirt_sarray_ptr sptr;
+    jvirt_barray_ptr bptr;
+
+    for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+      if (sptr->b_s_open) {  /* there may be no backing store */
+  sptr->b_s_open = FALSE;  /* prevent recursive close if error */
+  (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
+      }
+    }
+    mem->virt_sarray_list = NULL;
+    for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+      if (bptr->b_s_open) {  /* there may be no backing store */
+  bptr->b_s_open = FALSE;  /* prevent recursive close if error */
+  (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
+      }
+    }
+    mem->virt_barray_list = NULL;
+  }
+
+  /* Release large objects */
+  lhdr_ptr = mem->large_list[pool_id];
+  mem->large_list[pool_id] = NULL;
+
+  while (lhdr_ptr != NULL) {
+    large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next;
+    space_freed = lhdr_ptr->hdr.bytes_used +
+      lhdr_ptr->hdr.bytes_left +
+      SIZEOF(large_pool_hdr);
+    jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed);
+    mem->total_space_allocated -= space_freed;
+    lhdr_ptr = next_lhdr_ptr;
+  }
+
+  /* Release small objects */
+  shdr_ptr = mem->small_list[pool_id];
+  mem->small_list[pool_id] = NULL;
+
+  while (shdr_ptr != NULL) {
+    small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next;
+    space_freed = shdr_ptr->hdr.bytes_used +
+      shdr_ptr->hdr.bytes_left +
+      SIZEOF(small_pool_hdr);
+    jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
+    mem->total_space_allocated -= space_freed;
+    shdr_ptr = next_shdr_ptr;
+  }
+}
+
+
+/*
+ * Close up shop entirely.
+ * Note that this cannot be called unless cinfo->mem is non-NULL.
+ */
+
+METHODDEF(void)
+self_destruct (j_common_ptr cinfo)
+{
+  int pool;
+
+  /* Close all backing store, release all memory.
+   * Releasing pools in reverse order might help avoid fragmentation
+   * with some (brain-damaged) malloc libraries.
+   */
+  for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+    free_pool(cinfo, pool);
+  }
+
+  /* Release the memory manager control block too. */
+  jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr));
+  cinfo->mem = NULL;    /* ensures I will be called only once */
+
+  jpeg_mem_term(cinfo);    /* system-dependent cleanup */
+}
+
+
+/*
+ * Memory manager initialization.
+ * When this is called, only the error manager pointer is valid in cinfo!
+ */
+
+GLOBAL(void)
+jinit_memory_mgr (j_common_ptr cinfo)
+{
+  my_mem_ptr mem;
+  long max_to_use;
+  int pool;
+  size_t test_mac;
+
+  cinfo->mem = NULL;    /* for safety if init fails */
+
+  /* Check for configuration errors.
+   * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably
+   * doesn't reflect any real hardware alignment requirement.
+   * The test is a little tricky: for X>0, X and X-1 have no one-bits
+   * in common if and only if X is a power of 2, ie has only one one-bit.
+   * Some compilers may give an "unreachable code" warning here; ignore it.
+   */
+  if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
+    ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
+  /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be
+   * a multiple of SIZEOF(ALIGN_TYPE).
+   * Again, an "unreachable code" warning may be ignored here.
+   * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK.
+   */
+  test_mac = (size_t) MAX_ALLOC_CHUNK;
+  if ((long) test_mac != MAX_ALLOC_CHUNK ||
+      (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)
+    ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
+
+  max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */
+
+  /* Attempt to allocate memory manager's control block */
+  mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));
+
+  if (mem == NULL) {
+    jpeg_mem_term(cinfo);  /* system-dependent cleanup */
+    ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
+  }
+
+  /* OK, fill in the method pointers */
+  mem->pub.alloc_small = alloc_small;
+  mem->pub.alloc_large = alloc_large;
+  mem->pub.alloc_sarray = alloc_sarray;
+  mem->pub.alloc_barray = alloc_barray;
+#ifdef NEED_DARRAY
+  mem->pub.alloc_darray = alloc_darray;
+#endif
+  mem->pub.request_virt_sarray = request_virt_sarray;
+  mem->pub.request_virt_barray = request_virt_barray;
+  mem->pub.realize_virt_arrays = realize_virt_arrays;
+  mem->pub.access_virt_sarray = access_virt_sarray;
+  mem->pub.access_virt_barray = access_virt_barray;
+  mem->pub.free_pool = free_pool;
+  mem->pub.self_destruct = self_destruct;
+
+  /* Make MAX_ALLOC_CHUNK accessible to other modules */
+  mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK;
+
+  /* Initialize working state */
+  mem->pub.max_memory_to_use = max_to_use;
+
+  for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+    mem->small_list[pool] = NULL;
+    mem->large_list[pool] = NULL;
+  }
+  mem->virt_sarray_list = NULL;
+  mem->virt_barray_list = NULL;
+
+  mem->total_space_allocated = SIZEOF(my_memory_mgr);
+
+  /* Declare ourselves open for business */
+  cinfo->mem = & mem->pub;
+
+  /* Check for an environment variable JPEGMEM; if found, override the
+   * default max_memory setting from jpeg_mem_init.  Note that the
+   * surrounding application may again override this value.
+   * If your system doesn't support getenv(), define NO_GETENV to disable
+   * this feature.
+   */
+#ifndef NO_GETENV
+  { char * memenv;
+
+    if ((memenv = getenv("JPEGMEM")) != NULL) {
+      char ch = 'x';
+
+      if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
+  if (ch == 'm' || ch == 'M')
+    max_to_use *= 1000L;
+  mem->pub.max_memory_to_use = max_to_use * 1000L;
+      }
+    }
+  }
+#endif
+
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jmemnobs.c b/Utilities/ITK/Utilities/itkjpeg/jmemnobs.c
new file mode 100644
index 0000000000000000000000000000000000000000..6757d4b3c21960e809b6c4c1b420c71a4c81363d
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jmemnobs.c
@@ -0,0 +1,117 @@
+/*
+ * jmemnobs.c
+ *
+ * Copyright (C) 1992-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides a really simple implementation of the system-
+ * dependent portion of the JPEG memory manager.  This implementation
+ * assumes that no backing-store files are needed: all required space
+ * can be obtained from malloc().
+ * This is very portable in the sense that it'll compile on almost anything,
+ * but you'd better have lots of main memory (or virtual memory) if you want
+ * to process big images.
+ * Note that the max_memory_to_use option is ignored by this implementation.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h"    /* import the system-dependent declarations */
+
+#ifndef HAVE_STDLIB_H    /* <stdlib.h> should declare malloc(),free() */
+extern void * malloc JPP((size_t size));
+extern void free JPP((void *ptr));
+#endif
+
+
+/*
+ * Memory allocation and freeing are controlled by the regular library
+ * routines malloc() and free().
+ */
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+  (void)cinfo;
+  return (void *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+  (void)cinfo;(void)sizeofobject;
+  free(object);
+}
+
+
+/*
+ * "Large" objects are treated the same as "small" ones.
+ * NB: although we include FAR keywords in the routine declarations,
+ * this file won't actually work in 80x86 small/medium model; at least,
+ * you probably won't be able to process useful-size images in only 64KB.
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+  (void)cinfo;
+  return (void FAR *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+  (void)cinfo;(void)sizeofobject;
+  free(object);
+}
+
+
+/*
+ * This routine computes the total memory space available for allocation.
+ * Here we always say, "we got all you want bud!"
+ */
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+        long max_bytes_needed, long already_allocated)
+{
+  (void)cinfo;(void)min_bytes_needed;(void)already_allocated;
+  return max_bytes_needed;
+}
+
+
+/*
+ * Backing store (temporary file) management.
+ * Since jpeg_mem_available always promised the moon,
+ * this should never be called and we can just error out.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+       long total_bytes_needed)
+{
+  (void)info;(void)total_bytes_needed;
+  ERREXIT(cinfo, JERR_NO_BACKING_STORE);
+}
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required.  Here, there isn't any.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+  (void)cinfo;
+  return 0;      /* just set max_memory_to_use to 0 */
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+  (void)cinfo;
+  /* no work */
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jmemsys.h b/Utilities/ITK/Utilities/itkjpeg/jmemsys.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e8ee7ee2f4faf3063721770956ee757b95a702a
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jmemsys.h
@@ -0,0 +1,198 @@
+/*
+ * jmemsys.h
+ *
+ * Copyright (C) 1992-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file defines the interface between the system-independent
+ * and system-dependent portions of the JPEG memory manager.  No other
+ * modules need include it.  (The system-independent portion is jmemmgr.c;
+ * there are several different versions of the system-dependent portion.)
+ *
+ * This file works as-is for the system-dependent memory managers supplied
+ * in the IJG distribution.  You may need to modify it if you write a
+ * custom memory manager.  If system-dependent changes are needed in
+ * this file, the best method is to #ifdef them based on a configuration
+ * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR
+ * and USE_MAC_MEMMGR.
+ */
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_get_small    jGetSmall
+#define jpeg_free_small    jFreeSmall
+#define jpeg_get_large    jGetLarge
+#define jpeg_free_large    jFreeLarge
+#define jpeg_mem_available  jMemAvail
+#define jpeg_open_backing_store  jOpenBackStore
+#define jpeg_mem_init    jMemInit
+#define jpeg_mem_term    jMemTerm
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/*
+ * These two functions are used to allocate and release small chunks of
+ * memory.  (Typically the total amount requested through jpeg_get_small is
+ * no more than 20K or so; this will be requested in chunks of a few K each.)
+ * Behavior should be the same as for the standard library functions malloc
+ * and free; in particular, jpeg_get_small must return NULL on failure.
+ * On most systems, these ARE malloc and free.  jpeg_free_small is passed the
+ * size of the object being freed, just in case it's needed.
+ * On an 80x86 machine using small-data memory model, these manage near heap.
+ */
+
+EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject));
+EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object,
+          size_t sizeofobject));
+
+/*
+ * These two functions are used to allocate and release large chunks of
+ * memory (up to the total free space designated by jpeg_mem_available).
+ * The interface is the same as above, except that on an 80x86 machine,
+ * far pointers are used.  On most other machines these are identical to
+ * the jpeg_get/free_small routines; but we keep them separate anyway,
+ * in case a different allocation strategy is desirable for large chunks.
+ */
+
+EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo,
+               size_t sizeofobject));
+EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object,
+          size_t sizeofobject));
+
+/*
+ * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
+ * be requested in a single call to jpeg_get_large (and jpeg_get_small for that
+ * matter, but that case should never come into play).  This macro is needed
+ * to model the 64Kb-segment-size limit of far addressing on 80x86 machines.
+ * On those machines, we expect that jconfig.h will provide a proper value.
+ * On machines with 32-bit flat address spaces, any large constant may be used.
+ *
+ * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type
+ * size_t and will be a multiple of sizeof(align_type).
+ */
+
+#ifndef MAX_ALLOC_CHUNK    /* may be overridden in jconfig.h */
+#define MAX_ALLOC_CHUNK  1000000000L
+#endif
+
+/*
+ * This routine computes the total space still available for allocation by
+ * jpeg_get_large.  If more space than this is needed, backing store will be
+ * used.  NOTE: any memory already allocated must not be counted.
+ *
+ * There is a minimum space requirement, corresponding to the minimum
+ * feasible buffer sizes; jmemmgr.c will request that much space even if
+ * jpeg_mem_available returns zero.  The maximum space needed, enough to hold
+ * all working storage in memory, is also passed in case it is useful.
+ * Finally, the total space already allocated is passed.  If no better
+ * method is available, cinfo->mem->max_memory_to_use - already_allocated
+ * is often a suitable calculation.
+ *
+ * It is OK for jpeg_mem_available to underestimate the space available
+ * (that'll just lead to more backing-store access than is really necessary).
+ * However, an overestimate will lead to failure.  Hence it's wise to subtract
+ * a slop factor from the true available space.  5% should be enough.
+ *
+ * On machines with lots of virtual memory, any large constant may be returned.
+ * Conversely, zero may be returned to always use the minimum amount of memory.
+ */
+
+EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo,
+             long min_bytes_needed,
+             long max_bytes_needed,
+             long already_allocated));
+
+
+/*
+ * This structure holds whatever state is needed to access a single
+ * backing-store object.  The read/write/close method pointers are called
+ * by jmemmgr.c to manipulate the backing-store object; all other fields
+ * are private to the system-dependent backing store routines.
+ */
+
+#define TEMP_NAME_LENGTH   64  /* max length of a temporary file's name */
+
+
+#ifdef USE_MSDOS_MEMMGR    /* DOS-specific junk */
+
+typedef unsigned short XMSH;  /* type of extended-memory handles */
+typedef unsigned short EMSH;  /* type of expanded-memory handles */
+
+typedef union {
+  short file_handle;    /* DOS file handle if it's a temp file */
+  XMSH xms_handle;    /* handle if it's a chunk of XMS */
+  EMSH ems_handle;    /* handle if it's a chunk of EMS */
+} handle_union;
+
+#endif /* USE_MSDOS_MEMMGR */
+
+#ifdef USE_MAC_MEMMGR    /* Mac-specific junk */
+#include <Files.h>
+#endif /* USE_MAC_MEMMGR */
+
+
+typedef struct backing_store_struct * backing_store_ptr;
+
+typedef struct backing_store_struct {
+  /* Methods for reading/writing/closing this backing-store object */
+  JMETHOD(void, read_backing_store, (j_common_ptr cinfo,
+             backing_store_ptr info,
+             void FAR * buffer_address,
+             long file_offset, long byte_count));
+  JMETHOD(void, write_backing_store, (j_common_ptr cinfo,
+              backing_store_ptr info,
+              void FAR * buffer_address,
+              long file_offset, long byte_count));
+  JMETHOD(void, close_backing_store, (j_common_ptr cinfo,
+              backing_store_ptr info));
+
+  /* Private fields for system-dependent backing-store management */
+#ifdef USE_MSDOS_MEMMGR
+  /* For the MS-DOS manager (jmemdos.c), we need: */
+  handle_union handle;    /* reference to backing-store storage object */
+  char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
+#else
+#ifdef USE_MAC_MEMMGR
+  /* For the Mac manager (jmemmac.c), we need: */
+  short temp_file;    /* file reference number to temp file */
+  FSSpec tempSpec;    /* the FSSpec for the temp file */
+  char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
+#else
+  /* For a typical implementation with temp files, we need: */
+  FILE * temp_file;    /* stdio reference to temp file */
+  char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */
+#endif
+#endif
+} backing_store_info;
+
+
+/*
+ * Initial opening of a backing-store object.  This must fill in the
+ * read/write/close pointers in the object.  The read/write routines
+ * may take an error exit if the specified maximum file size is exceeded.
+ * (If jpeg_mem_available always returns a large value, this routine can
+ * just take an error exit.)
+ */
+
+EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo,
+            backing_store_ptr info,
+            long total_bytes_needed));
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required.  jpeg_mem_init will be called before anything is
+ * allocated (and, therefore, nothing in cinfo is of use except the error
+ * manager pointer).  It should return a suitable default value for
+ * max_memory_to_use; this may subsequently be overridden by the surrounding
+ * application.  (Note that max_memory_to_use is only important if
+ * jpeg_mem_available chooses to consult it ... no one else will.)
+ * jpeg_mem_term may assume that all requested memory has been freed and that
+ * all opened backing-store objects have been closed.
+ */
+
+EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo));
+EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo));
diff --git a/Utilities/ITK/Utilities/itkjpeg/jmorecfg.h.in b/Utilities/ITK/Utilities/itkjpeg/jmorecfg.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..60fb42b3c9414ef053f465ecd1b2f1b7aec5996b
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jmorecfg.h.in
@@ -0,0 +1,437 @@
+/*
+ * jmorecfg.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains additional configuration options that customize the
+ * JPEG software for special applications or support machine-dependent
+ * optimizations.  Most users will not need to touch this file.
+ */
+
+#include "itkjpeg/jpegDllConfig.h"
+
+/*
+ * Define BITS_IN_JSAMPLE as either
+ *   8   for 8-bit sample values (the usual setting)
+ *   12  for 12-bit sample values
+ * Only 8 and 12 are legal data precisions for lossy JPEG according to the
+ * JPEG standard, and the IJG code does not support anything else!
+ * We do not support run-time selection of data precision, sorry.
+ */
+
+/*#define BITS_IN_JSAMPLE  8*//* use 8 or 12 (or 16 only for lossless) */
+#define BITS_IN_JSAMPLE @CMAKE_BITS_IN_JSAMPLE@
+
+/*
+ * Maximum number of components (color channels) allowed in JPEG image.
+ * To meet the letter of the JPEG spec, set this to 255.  However, darn
+ * few applications need more than 4 channels (maybe 5 for CMYK + alpha
+ * mask).  We recommend 10 as a reasonable compromise; use 4 if you are
+ * really short on memory.  (Each allowed component costs a hundred or so
+ * bytes of storage, whether actually used in an image or not.)
+ */
+
+#define MAX_COMPONENTS  10  /* maximum number of image components */
+
+
+/*
+ * Basic data types.
+ * You may need to change these if you have a machine with unusual data
+ * type sizes; for example, "char" not 8 bits, "short" not 16 bits,
+ * or "long" not 32 bits.  We don't care whether "int" is 16 or 32 bits,
+ * but it had better be at least 16.
+ */
+
+/* Representation of a single sample (pixel element value).
+ * We frequently allocate large arrays of these, so it's important to keep
+ * them small.  But if you have memory to burn and access to char or short
+ * arrays is very slow on your hardware, you might want to change these.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+/* JSAMPLE should be the smallest type that will hold the values 0..255.
+ * You can use a signed char by having GETJSAMPLE mask it with 0xFF.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JSAMPLE;
+#define GETJSAMPLE(value)  ((int) (value))
+
+#else /* not HAVE_UNSIGNED_CHAR */
+
+typedef char JSAMPLE;
+#ifdef CHAR_IS_UNSIGNED
+#define GETJSAMPLE(value)  ((int) (value))
+#else
+#define GETJSAMPLE(value)  ((int) (value) & 0xFF)
+#endif /* CHAR_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_CHAR */
+
+#define MAXJSAMPLE  255
+#define CENTERJSAMPLE  128
+
+#endif /* BITS_IN_JSAMPLE == 8 */
+
+
+#if BITS_IN_JSAMPLE == 12
+/* JSAMPLE should be the smallest type that will hold the values 0..4095.
+ * On nearly all machines "short" will do nicely.
+ */
+
+typedef short JSAMPLE;
+#define GETJSAMPLE(value)  ((int) (value))
+
+#define MAXJSAMPLE  4095
+#define CENTERJSAMPLE  2048
+
+#endif /* BITS_IN_JSAMPLE == 12 */
+
+
+#if BITS_IN_JSAMPLE == 16
+/* JSAMPLE should be the smallest type that will hold the values 0..65535.
+ * You can use a signed short by having GETJSAMPLE mask it with 0xFFFF.
+ */
+
+#ifdef HAVE_UNSIGNED_SHORT
+
+typedef unsigned short JSAMPLE;
+#define GETJSAMPLE(value)  ((int) (value))
+
+#else /* not HAVE_UNSIGNED_SHORT */
+
+typedef short JSAMPLE;
+#ifdef SHORT_IS_UNSIGNED
+#define GETJSAMPLE(value)  ((int) (value))
+#else
+#define GETJSAMPLE(value)  ((int) (value) & 0xFFFF)
+#endif /* SHORT_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_SHORT */
+
+#define MAXJSAMPLE  65535
+#define CENTERJSAMPLE  32768
+
+#endif /* BITS_IN_JSAMPLE == 16 */
+
+
+/* Representation of a DCT frequency coefficient.
+ * This should be a signed value of at least 16 bits; "short" is usually OK.
+ * Again, we allocate large arrays of these, but you can change to int
+ * if you have memory to burn and "short" is really slow.
+ */
+
+typedef short JCOEF;
+
+
+/* Representation of a spatial difference value.
+ * This should be a signed value of at least 16 bits; int is usually OK.
+ */
+
+typedef int JDIFF;
+
+
+/* Compressed datastreams are represented as arrays of JOCTET.
+ * These must be EXACTLY 8 bits wide, at least once they are written to
+ * external storage.  Note that when using the stdio data source/destination
+ * managers, this is also the data type passed to fread/fwrite.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JOCTET;
+#define GETJOCTET(value)  (value)
+
+#else /* not HAVE_UNSIGNED_CHAR */
+
+typedef char JOCTET;
+#ifdef CHAR_IS_UNSIGNED
+#define GETJOCTET(value)  (value)
+#else
+#define GETJOCTET(value)  ((value) & 0xFF)
+#endif /* CHAR_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+/* These typedefs are used for various table entries and so forth.
+ * They must be at least as wide as specified; but making them too big
+ * won't cost a huge amount of memory, so we don't provide special
+ * extraction code like we did for JSAMPLE.  (In other words, these
+ * typedefs live at a different point on the speed/space tradeoff curve.)
+ */
+
+/* UINT8 must hold at least the values 0..255. */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char UINT8;
+#else /* not HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char UINT8;
+#else /* not CHAR_IS_UNSIGNED */
+typedef short UINT8;
+#endif /* CHAR_IS_UNSIGNED */
+#endif /* HAVE_UNSIGNED_CHAR */
+
+/* UINT16 must hold at least the values 0..65535. */
+
+#ifdef HAVE_UNSIGNED_SHORT
+typedef unsigned short UINT16;
+#else /* not HAVE_UNSIGNED_SHORT */
+typedef unsigned int UINT16;
+#endif /* HAVE_UNSIGNED_SHORT */
+
+/* INT16 must hold at least the values -32768..32767. */
+
+#ifndef XMD_H      /* X11/xmd.h correctly defines INT16 */
+typedef short INT16;
+#endif
+
+/* INT32 must hold at least signed 32-bit values. */
+/* X11/xmd.h and basetsd.h correctly defines INT32 */
+
+#if !defined(XMD_H) && !(defined(_BASETSD_H_) || defined(_BASETSD_H))
+typedef int INT32;
+#endif
+
+/* Datatype used for image dimensions.  The JPEG standard only supports
+ * images up to 64K*64K due to 16-bit fields in SOF markers.  Therefore
+ * "unsigned int" is sufficient on all machines.  However, if you need to
+ * handle larger images and you don't mind deviating from the spec, you
+ * can change this datatype.
+ */
+
+typedef unsigned int JDIMENSION;
+
+#define JPEG_MAX_DIMENSION  65500L  /* a tad under 64K to prevent overflows */
+
+
+/* These macros are used in all function definitions and extern declarations.
+ * You could modify them if you need to change function linkage conventions;
+ * in particular, you'll need to do that to make the library a Windows DLL.
+ * Another application is to make all functions global for use with debuggers
+ * or code profilers that require it.
+ */
+
+/* a function called through method pointers: */
+#define METHODDEF(type)    static type
+/* a function used only in its module: */
+#define LOCAL(type)    static type
+/* a function referenced thru EXTERNs: */
+#if defined( _WIN32 ) && defined (JPEGDLL)
+#define GLOBAL(type)            __declspec(dllexport) type
+#else
+#define GLOBAL(type)            type
+#endif
+
+/* a reference to a GLOBAL function: */
+#if defined(_WIN32) && !defined(JPEGSTATIC)
+#ifdef JPEGDLL
+/* Win32, building a dll */
+#define EXTERN(type)            __declspec(dllexport) type
+#else
+/* Win32, not building a dll but using the dll */
+#define EXTERN(type)            __declspec(dllimport) type
+#endif
+#else
+/* not a Win32 system or building a static Win32 lib */
+#define EXTERN(type)            extern type
+#endif
+
+
+/* This macro is used to declare a "method", that is, a function pointer.
+ * We want to supply prototype parameters if the compiler can cope.
+ * Note that the arglist parameter must be parenthesized!
+ * Again, you can customize this if you need special linkage keywords.
+ */
+
+#ifdef HAVE_PROTOTYPES
+#define JMETHOD(type,methodname,arglist)  type (*methodname) arglist
+#else
+#define JMETHOD(type,methodname,arglist)  type (*methodname) ()
+#endif
+
+
+/* Here is the pseudo-keyword for declaring pointers that must be "far"
+ * on 80x86 machines.  Most of the specialized coding for 80x86 is handled
+ * by just saying "FAR *" where such a pointer is needed.  In a few places
+ * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
+ */
+
+#ifndef FAR
+#ifdef NEED_FAR_POINTERS
+#define FAR  far
+#else
+#define FAR
+#endif
+#endif
+
+
+/*
+ * On a few systems, type boolean and/or its values FALSE, TRUE may appear
+ * in standard header files.  Or you may have conflicts with application-
+ * specific header files that you want to include together with these files.
+ * Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
+ */
+
+#ifndef HAVE_BOOLEAN
+typedef int boolean;
+#endif
+#ifndef FALSE      /* in case these macros already exist */
+#define FALSE  0    /* values of boolean */
+#endif
+#ifndef TRUE
+#define TRUE  1
+#endif
+
+
+/*
+ * The remaining options affect code selection within the JPEG library,
+ * but they don't need to be visible to most applications using the library.
+ * To minimize application namespace pollution, the symbols won't be
+ * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
+ */
+
+#ifdef JPEG_INTERNALS
+#define JPEG_INTERNAL_OPTIONS
+#endif
+
+#ifdef JPEG_INTERNAL_OPTIONS
+
+
+/*
+ * These defines indicate whether to include various optional functions.
+ * Undefining some of these symbols will produce a smaller but less capable
+ * library.  Note that you can leave certain source files out of the
+ * compilation/linking process if you've #undef'd the corresponding symbols.
+ * (You may HAVE to do that if your compiler doesn't like null source files.)
+ */
+
+/* Arithmetic coding is unsupported for legal reasons.  Complaints to IBM. */
+
+/* Capability options common to encoder and decoder: */
+
+#define DCT_ISLOW_SUPPORTED  /* slow but accurate integer algorithm */
+#define DCT_IFAST_SUPPORTED  /* faster, less accurate integer method */
+#define DCT_FLOAT_SUPPORTED  /* floating-point: accurate, fast on fast HW */
+
+/* Encoder capability options: */
+
+#undef  C_ARITH_CODING_SUPPORTED    /* Arithmetic coding back end? */
+#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define C_PROGRESSIVE_SUPPORTED      /* Progressive JPEG? (Requires MULTISCAN)*/
+#define C_LOSSLESS_SUPPORTED      /* Lossless JPEG? */
+#define ENTROPY_OPT_SUPPORTED      /* Optimization of entropy coding parms? */
+/* Note: if you selected 12-bit data precision, it is dangerous to turn off
+ * ENTROPY_OPT_SUPPORTED.  The standard Huffman tables are only good for 8-bit
+ * precision, so jcshuff.c normally uses entropy optimization to compute
+ * usable tables for higher precision.  If you don't want to do optimization,
+ * you'll have to supply different default Huffman tables.
+ * The exact same statements apply for progressive and lossless JPEG:
+ * the default tables don't work for progressive mode or lossless mode.
+ * (This may get fixed, however.)
+ */
+#define INPUT_SMOOTHING_SUPPORTED   /* Input image smoothing option? */
+
+/* Decoder capability options: */
+
+#undef  D_ARITH_CODING_SUPPORTED    /* Arithmetic coding back end? */
+#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define D_PROGRESSIVE_SUPPORTED      /* Progressive JPEG? (Requires MULTISCAN)*/
+#define D_LOSSLESS_SUPPORTED      /* Lossless JPEG? */
+#define SAVE_MARKERS_SUPPORTED      /* jpeg_save_markers() needed? */
+#define BLOCK_SMOOTHING_SUPPORTED   /* Block smoothing? (Progressive only) */
+#define IDCT_SCALING_SUPPORTED      /* Output rescaling via IDCT? */
+#undef  UPSAMPLE_SCALING_SUPPORTED  /* Output rescaling at upsample stage? */
+#define UPSAMPLE_MERGING_SUPPORTED  /* Fast path for sloppy upsampling? */
+#define QUANT_1PASS_SUPPORTED      /* 1-pass color quantization? */
+#define QUANT_2PASS_SUPPORTED      /* 2-pass color quantization? */
+
+/* more capability options later, no doubt */
+
+
+/*
+ * Ordering of RGB data in scanlines passed to or from the application.
+ * If your application wants to deal with data in the order B,G,R, just
+ * change these macros.  You can also deal with formats such as R,G,B,X
+ * (one extra byte per pixel) by changing RGB_PIXELSIZE.  Note that changing
+ * the offsets will also change the order in which colormap data is organized.
+ * RESTRICTIONS:
+ * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
+ * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
+ *    useful if you are using JPEG color spaces other than YCbCr or grayscale.
+ * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
+ *    is not 3 (they don't understand about dummy color components!).  So you
+ *    can't use color quantization if you change that value.
+ */
+
+#define RGB_RED    0  /* Offset of Red in an RGB scanline element */
+#define RGB_GREEN  1  /* Offset of Green */
+#define RGB_BLUE  2  /* Offset of Blue */
+#define RGB_PIXELSIZE  3  /* JSAMPLEs per RGB scanline element */
+
+
+/* Definitions for speed-related optimizations. */
+
+
+/* If your compiler supports inline functions, define INLINE
+ * as the inline keyword; otherwise define it as empty.
+ */
+
+#ifndef INLINE
+#ifdef __GNUC__      /* for instance, GNU C knows about inline */
+#define INLINE __inline__
+#endif
+#ifndef INLINE
+#define INLINE      /* default is to define it as empty */
+#endif
+#endif
+
+
+/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
+ * two 16-bit shorts is faster than multiplying two ints.  Define MULTIPLIER
+ * as short on such a machine.  MULTIPLIER must be at least 16 bits wide.
+ */
+
+#ifndef MULTIPLIER
+#define MULTIPLIER  int    /* type for fastest integer multiply */
+#endif
+
+
+/* FAST_FLOAT should be either float or double, whichever is done faster
+ * by your compiler.  (Note that this type is only used in the floating point
+ * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
+ * Typically, float is faster in ANSI C compilers, while double is faster in
+ * pre-ANSI compilers (because they insist on converting to double anyway).
+ * The code below therefore chooses float if we have ANSI-style prototypes.
+ */
+
+#ifndef FAST_FLOAT
+#ifdef HAVE_PROTOTYPES
+#define FAST_FLOAT  float
+#else
+#define FAST_FLOAT  double
+#endif
+#endif
+
+#if defined ( _MSC_VER )
+#pragma warning ( disable : 4100 )
+#pragma warning ( disable : 4115 )
+#pragma warning ( disable : 4127 )
+#pragma warning ( disable : 4244 )
+#pragma warning ( disable : 4251 )
+#pragma warning ( disable : 4267 )
+#pragma warning ( disable : 4305 )
+#pragma warning ( disable : 4309 )
+#pragma warning ( disable : 4706 )
+#pragma warning ( disable : 4786 )
+#pragma warning ( disable : 4057 )
+#pragma warning ( disable : 4189 )
+#pragma warning ( disable : 4505 )
+#endif
+
+
+#endif /* JPEG_INTERNAL_OPTIONS */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jpegDllConfig.h.in b/Utilities/ITK/Utilities/itkjpeg/jpegDllConfig.h.in
new file mode 100644
index 0000000000000000000000000000000000000000..0baca6474e8f4cf2800d93639572268639df0e26
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jpegDllConfig.h.in
@@ -0,0 +1,6 @@
+#ifndef _jpegDllConfig_h
+#define _jpegDllConfig_h
+
+#cmakedefine JPEGSTATIC
+
+#endif
diff --git a/Utilities/ITK/Utilities/itkjpeg/jpegint.h b/Utilities/ITK/Utilities/itkjpeg/jpegint.h
new file mode 100644
index 0000000000000000000000000000000000000000..684dada046a2e3eec675dca64e98bb9fd38fd200
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jpegint.h
@@ -0,0 +1,365 @@
+/*
+ * jpegint.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides common declarations for the various JPEG modules.
+ * These declarations are considered internal to the JPEG library; most
+ * applications using the library shouldn't need to include this file.
+ */
+
+
+/* Declarations for both compression & decompression */
+
+typedef enum {      /* Operating modes for buffer controllers */
+  JBUF_PASS_THRU,    /* Plain stripwise operation */
+  /* Remaining modes require a full-image buffer to have been created */
+  JBUF_SAVE_SOURCE,  /* Run source subobject only, save output */
+  JBUF_CRANK_DEST,  /* Run dest subobject only, using saved data */
+  JBUF_SAVE_AND_PASS  /* Run both subobjects, save output */
+} J_BUF_MODE;
+
+/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
+#define CSTATE_START  100  /* after create_compress */
+#define CSTATE_SCANNING  101  /* start_compress done, write_scanlines OK */
+#define CSTATE_RAW_OK  102  /* start_compress done, write_raw_data OK */
+#define CSTATE_WRCOEFS  103  /* jpeg_write_coefficients done */
+#define DSTATE_START  200  /* after create_decompress */
+#define DSTATE_INHEADER  201  /* reading header markers, no SOS yet */
+#define DSTATE_READY  202  /* found SOS, ready for start_decompress */
+#define DSTATE_PRELOAD  203  /* reading multiscan file in start_decompress*/
+#define DSTATE_PRESCAN  204  /* performing dummy pass for 2-pass quant */
+#define DSTATE_SCANNING  205  /* start_decompress done, read_scanlines OK */
+#define DSTATE_RAW_OK  206  /* start_decompress done, read_raw_data OK */
+#define DSTATE_BUFIMAGE  207  /* expecting jpeg_start_output */
+#define DSTATE_BUFPOST  208  /* looking for SOS/EOI in jpeg_finish_output */
+#define DSTATE_RDCOEFS  209  /* reading file in jpeg_read_coefficients */
+#define DSTATE_STOPPING  210  /* looking for EOI in jpeg_finish_decompress */
+
+
+/* Declarations for compression modules */
+
+/* Master control module */
+struct jpeg_comp_master {
+  JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
+  JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
+  JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
+
+  /* State variables made visible to other modules */
+  boolean call_pass_startup;  /* True if pass_startup must be called */
+  boolean is_last_pass;    /* True during last pass */
+};
+
+/* Main buffer control (downsampled-data buffer) */
+struct jpeg_c_main_controller {
+  JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+  JMETHOD(void, process_data, (j_compress_ptr cinfo,
+             JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+             JDIMENSION in_rows_avail));
+};
+
+/* Compression preprocessing (downsampling input buffer control) */
+struct jpeg_c_prep_controller {
+  JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+  JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
+           JSAMPARRAY input_buf,
+           JDIMENSION *in_row_ctr,
+           JDIMENSION in_rows_avail,
+           JSAMPIMAGE output_buf,
+           JDIMENSION *out_row_group_ctr,
+           JDIMENSION out_row_groups_avail));
+};
+
+/* Compression codec (compressor proper) */
+struct jpeg_c_codec {
+  JMETHOD(void, entropy_start_pass, (j_compress_ptr cinfo,
+             boolean gather_statistics));
+  JMETHOD(void, entropy_finish_pass, (j_compress_ptr cinfo));
+  JMETHOD(boolean, need_optimization_pass, (j_compress_ptr cinfo));
+  JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+  JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
+           JSAMPIMAGE input_buf));
+};
+
+/* Colorspace conversion */
+struct jpeg_color_converter {
+  JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+  JMETHOD(void, color_convert, (j_compress_ptr cinfo,
+        JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+        JDIMENSION output_row, int num_rows));
+};
+
+/* Downsampling */
+struct jpeg_downsampler {
+  JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+  JMETHOD(void, downsample, (j_compress_ptr cinfo,
+           JSAMPIMAGE input_buf, JDIMENSION in_row_index,
+           JSAMPIMAGE output_buf,
+           JDIMENSION out_row_group_index));
+
+  boolean need_context_rows;  /* TRUE if need rows above & below */
+};
+
+/* Marker writing */
+struct jpeg_marker_writer {
+  JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
+  JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
+  JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
+  JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
+  JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
+  /* These routines are exported to allow insertion of extra markers */
+  /* Probably only COM and APPn markers should be written this way */
+  JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker,
+              unsigned int datalen));
+  JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val));
+};
+
+
+/* Declarations for decompression modules */
+
+/* Master control module */
+struct jpeg_decomp_master {
+  JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
+  JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
+
+  /* State variables made visible to other modules */
+  boolean is_dummy_pass;  /* True during 1st pass for 2-pass quant */
+};
+
+/* Input control module */
+struct jpeg_input_controller {
+  JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
+  JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
+  JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
+  JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
+
+  /* State variables made visible to other modules */
+  boolean has_multiple_scans;  /* True if file has multiple scans */
+  boolean eoi_reached;    /* True when EOI has been consumed */
+};
+
+/* Main buffer control (downsampled-data buffer) */
+struct jpeg_d_main_controller {
+  JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+  JMETHOD(void, process_data, (j_decompress_ptr cinfo,
+             JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+             JDIMENSION out_rows_avail));
+};
+
+/* Decompression codec (decompressor proper) */
+struct jpeg_d_codec {
+  JMETHOD(void, calc_output_dimensions, (j_decompress_ptr cinfo));
+  JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
+  JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
+  JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
+  JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
+         JSAMPIMAGE output_buf));
+};
+
+/* Decompression postprocessing (color quantization buffer control) */
+struct jpeg_d_post_controller {
+  JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+  JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
+            JSAMPIMAGE input_buf,
+            JDIMENSION *in_row_group_ctr,
+            JDIMENSION in_row_groups_avail,
+            JSAMPARRAY output_buf,
+            JDIMENSION *out_row_ctr,
+            JDIMENSION out_rows_avail));
+};
+
+/* Marker reading & parsing */
+struct jpeg_marker_reader {
+  JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
+  /* Read markers until SOS or EOI.
+   * Returns same codes as are defined for jpeg_consume_input:
+   * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+   */
+  JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
+  /* Read a restart marker --- exported for use by entropy decoder only */
+  jpeg_marker_parser_method read_restart_marker;
+
+  /* State of marker reader --- nominally internal, but applications
+   * supplying COM or APPn handlers might like to know the state.
+   */
+  boolean saw_SOI;    /* found SOI? */
+  boolean saw_SOF;    /* found SOF? */
+  int next_restart_num;    /* next restart number expected (0-7) */
+  unsigned int discarded_bytes;  /* # of bytes skipped looking for a marker */
+};
+
+/* Upsampling (note that upsampler must also call color converter) */
+struct jpeg_upsampler {
+  JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+  JMETHOD(void, upsample, (j_decompress_ptr cinfo,
+         JSAMPIMAGE input_buf,
+         JDIMENSION *in_row_group_ctr,
+         JDIMENSION in_row_groups_avail,
+         JSAMPARRAY output_buf,
+         JDIMENSION *out_row_ctr,
+         JDIMENSION out_rows_avail));
+
+  boolean need_context_rows;  /* TRUE if need rows above & below */
+};
+
+/* Colorspace conversion */
+struct jpeg_color_deconverter {
+  JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+  JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
+        JSAMPIMAGE input_buf, JDIMENSION input_row,
+        JSAMPARRAY output_buf, int num_rows));
+};
+
+/* Color quantization or color precision reduction */
+struct jpeg_color_quantizer {
+  JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
+  JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
+         JSAMPARRAY input_buf, JSAMPARRAY output_buf,
+         int num_rows));
+  JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
+  JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
+};
+
+
+/* Miscellaneous useful macros */
+
+#undef MAX
+#define MAX(a,b)  ((a) > (b) ? (a) : (b))
+#undef MIN
+#define MIN(a,b)  ((a) < (b) ? (a) : (b))
+
+
+/* We assume that right shift corresponds to signed division by 2 with
+ * rounding towards minus infinity.  This is correct for typical "arithmetic
+ * shift" instructions that shift in copies of the sign bit.  But some
+ * C compilers implement >> with an unsigned shift.  For these machines you
+ * must define RIGHT_SHIFT_IS_UNSIGNED.
+ * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
+ * It is only applied with constant shift counts.  SHIFT_TEMPS must be
+ * included in the variables of any routine using RIGHT_SHIFT.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define SHIFT_TEMPS  INT32 shift_temp;
+#define RIGHT_SHIFT(x,shft)  \
+  ((shift_temp = (x)) < 0 ? \
+   (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
+   (shift_temp >> (shft)))
+#else
+#define SHIFT_TEMPS
+#define RIGHT_SHIFT(x,shft)  ((x) >> (shft))
+#endif
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jinit_c_codec    jICCodec
+#define jinit_c_diff_controller  jICDiffC
+#define jinit_lossy_c_codec  jILossyC
+#define jinit_lossless_c_codec  jILosslessC
+#define jinit_compress_master  jICompress
+#define jinit_c_master_control  jICMaster
+#define jinit_c_main_controller  jICMainC
+#define jinit_c_prep_controller  jICPrepC
+#define jinit_c_coef_controller  jICCoefC
+#define jinit_color_converter  jICColor
+#define jinit_downsampler  jIDownsampler
+#define jinit_forward_dct  jIFDCT
+#define jinit_shuff_encoder  jISHEncoder
+#define jinit_phuff_encoder  jIPHEncoder
+#define jinit_arith_encoder  jIAEncoder
+#define jinit_marker_writer  jIMWriter
+#define jinit_d_codec    jIDCodec
+#define jinit_lossy_d_codec  jILossyD
+#define jinit_lossless_d_codec  jILosslsD
+#define jinit_master_decompress  jIDMaster
+#define jinit_d_main_controller  jIDMainC
+#define jinit_d_coef_controller  jIDCoefC
+#define jinit_d_diff_controller  jIDDiffC
+#define jinit_d_post_controller  jIDPostC
+#define jinit_input_controller  jIInCtlr
+#define jinit_marker_reader  jIMReader
+#define jinit_shuff_decoder  jISHDecoder
+#define jinit_phuff_decoder  jIPHDecoder
+#define jinit_arith_decoder  jIADecoder
+#define jinit_lhuff_decoder  jILHDecoder
+#define jinit_undifferencer  jIUndiff
+#define jinit_d_scaler    jIDScaler
+#define jinit_inverse_dct  jIIDCT
+#define jinit_upsampler    jIUpsampler
+#define jinit_color_deconverter  jIDColor
+#define jinit_1pass_quantizer  jI1Quant
+#define jinit_2pass_quantizer  jI2Quant
+#define jinit_merged_upsampler  jIMUpsampler
+#define jinit_memory_mgr  jIMemMgr
+#define jdiv_round_up    jDivRound
+#define jround_up    jRound
+#define jcopy_sample_rows  jCopySamples
+#define jcopy_block_row    jCopyBlocks
+#define jzero_far    jZeroFar
+#define jpeg_zigzag_order  jZIGTable
+#define jpeg_natural_order  jZAGTable
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Compression module initialization routines */
+EXTERN(void) jinit_c_codec JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_c_diff_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer));
+EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
+           boolean transcode_only));
+EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
+            boolean need_full_buffer));
+EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
+            boolean need_full_buffer));
+EXTERN(void) jinit_compressor JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo));
+/* Decompression module initialization routines */
+EXTERN(void) jinit_d_codec JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_diff_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer));
+EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
+            boolean need_full_buffer));
+EXTERN(void) jinit_decompressor JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
+            boolean need_full_buffer));
+EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
+/* Memory manager initialization */
+EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
+
+/* Utility routines in jutils.c */
+EXTERN(long) jdiv_round_up JPP((long a, long b));
+EXTERN(long) jround_up JPP((long a, long b));
+EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
+            JSAMPARRAY output_array, int dest_row,
+            int num_rows, JDIMENSION num_cols));
+EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
+          JDIMENSION num_blocks));
+EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero));
+/* Constant tables in jutils.c */
+#if 0        /* This table is not actually needed in v6a */
+extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
+#endif
+extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
+
+/* Suppress undefined-structure complaints if necessary. */
+
+#ifdef INCOMPLETE_TYPES_BROKEN
+#ifndef AM_MEMORY_MANAGER  /* only jmemmgr.c defines these */
+struct jvirt_sarray_control { long dummy; };
+struct jvirt_barray_control { long dummy; };
+#endif
+#endif /* INCOMPLETE_TYPES_BROKEN */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jpeglib.h b/Utilities/ITK/Utilities/itkjpeg/jpeglib.h
new file mode 100644
index 0000000000000000000000000000000000000000..02c2d186b669871ca2476116e489512aa523166d
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jpeglib.h
@@ -0,0 +1,1131 @@
+/*
+ * jpeglib.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the application interface for the JPEG library.
+ * Most applications using the library need only include this file,
+ * and perhaps jerror.h if they want to know the exact error codes.
+ */
+
+#ifndef JPEGLIB_H
+#define JPEGLIB_H
+
+/*
+ * First we include the configuration files that record how this
+ * installation of the JPEG library is set up.  jconfig.h can be
+ * generated automatically for many systems.  jmorecfg.h contains
+ * manual configuration options that most people need not worry about.
+ */
+
+#ifndef JCONFIG_INCLUDED  /* in case jinclude.h already did */
+#include "jconfig.h"    /* widely used configuration options */
+#endif
+#include "jmorecfg.h"    /* seldom changed options */
+
+
+/* Version ID for the JPEG library.
+ * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
+ */
+
+#define JPEG_LIB_VERSION  62  /* Version 6b */
+
+
+/* Various constants determining the sizes of things.
+ * All of these are specified by the JPEG standard, so don't change them
+ * if you want to be compatible.
+ */
+
+#define DCTSIZE        8  /* The basic DCT block is 8x8 samples */
+#define DCTSIZE2      64  /* DCTSIZE squared; # of elements in a block */
+#define NUM_QUANT_TBLS      4  /* Quantization tables are numbered 0..3 */
+#define NUM_HUFF_TBLS       4  /* Huffman tables are numbered 0..3 */
+#define NUM_ARITH_TBLS      16  /* Arith-coding tables are numbered 0..15 */
+#define MAX_COMPS_IN_SCAN   4  /* JPEG limit on # of components in one scan */
+#define MAX_SAMP_FACTOR     4  /* JPEG limit on sampling factors */
+/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard;
+ * the PostScript DCT filter can emit files with many more than 10 data units
+ * per MCU.
+ * If you happen to run across such a file, you can up D_MAX_DATA_UNITS_IN_MCU
+ * to handle it.  We even let you do this from the jconfig.h file.  However,
+ * we strongly discourage changing C_MAX_DATA_UNITS_IN_MCU; just because Adobe
+ * sometimes emits noncompliant files doesn't mean you should too.
+ */
+#define C_MAX_DATA_UNITS_IN_MCU   10 /* compressor's limit on data units/MCU */
+#ifndef D_MAX_DATA_UNITS_IN_MCU
+#define D_MAX_DATA_UNITS_IN_MCU   10 /* decompressor's limit on data units/MCU */
+#endif
+
+
+/* Data structures for images (arrays of samples and of DCT coefficients).
+ * On 80x86 machines, the image arrays are too big for near pointers,
+ * but the pointer arrays can fit in near memory.
+ */
+
+typedef JSAMPLE FAR *JSAMPROW;  /* ptr to one image row of pixel samples. */
+typedef JSAMPROW *JSAMPARRAY;  /* ptr to some rows (a 2-D sample array) */
+typedef JSAMPARRAY *JSAMPIMAGE;  /* a 3-D sample array: top index is color */
+
+typedef JCOEF JBLOCK[DCTSIZE2];  /* one block of coefficients */
+typedef JBLOCK FAR *JBLOCKROW;  /* pointer to one row of coefficient blocks */
+typedef JBLOCKROW *JBLOCKARRAY;    /* a 2-D array of coefficient blocks */
+typedef JBLOCKARRAY *JBLOCKIMAGE;  /* a 3-D array of coefficient blocks */
+
+typedef JCOEF FAR *JCOEFPTR;  /* useful in a couple of places */
+
+typedef JDIFF FAR *JDIFFROW;  /* pointer to one row of difference values */
+typedef JDIFFROW *JDIFFARRAY;  /* ptr to some rows (a 2-D diff array) */
+typedef JDIFFARRAY *JDIFFIMAGE;  /* a 3-D diff array: top index is color */
+
+
+/* Types for JPEG compression parameters and working tables. */
+
+
+/* DCT coefficient quantization tables. */
+
+typedef struct {
+  /* This array gives the coefficient quantizers in natural array order
+   * (not the zigzag order in which they are stored in a JPEG DQT marker).
+   * CAUTION: IJG versions prior to v6a kept this array in zigzag order.
+   */
+  UINT16 quantval[DCTSIZE2];  /* quantization step for each coefficient */
+  /* This field is used only during compression.  It's initialized FALSE when
+   * the table is created, and set TRUE when it's been output to the file.
+   * You could suppress output of a table by setting this to TRUE.
+   * (See jpeg_suppress_tables for an example.)
+   */
+  boolean sent_table;    /* TRUE when table has been output */
+} JQUANT_TBL;
+
+
+/* Huffman coding tables. */
+
+typedef struct {
+  /* These two fields directly represent the contents of a JPEG DHT marker */
+  UINT8 bits[17];    /* bits[k] = # of symbols with codes of */
+        /* length k bits; bits[0] is unused */
+  UINT8 huffval[256];    /* The symbols, in order of incr code length */
+  /* This field is used only during compression.  It's initialized FALSE when
+   * the table is created, and set TRUE when it's been output to the file.
+   * You could suppress output of a table by setting this to TRUE.
+   * (See jpeg_suppress_tables for an example.)
+   */
+  boolean sent_table;    /* TRUE when table has been output */
+} JHUFF_TBL;
+
+
+/* Basic info about one component (color channel). */
+
+typedef struct {
+  /* These values are fixed over the whole image. */
+  /* For compression, they must be supplied by parameter setup; */
+  /* for decompression, they are read from the SOF marker. */
+  int component_id;    /* identifier for this component (0..255) */
+  int component_index;    /* its index in SOF or cinfo->comp_info[] */
+  int h_samp_factor;    /* horizontal sampling factor (1..4) */
+  int v_samp_factor;    /* vertical sampling factor (1..4) */
+  int quant_tbl_no;    /* quantization table selector (0..3) */
+  /* These values may vary between scans. */
+  /* For compression, they must be supplied by parameter setup; */
+  /* for decompression, they are read from the SOS marker. */
+  /* The decompressor output side may not use these variables. */
+  int dc_tbl_no;    /* DC entropy table selector (0..3) */
+  int ac_tbl_no;    /* AC entropy table selector (0..3) */
+  
+  /* Remaining fields should be treated as private by applications. */
+  
+  /* These values are computed during compression or decompression startup: */
+  /* Component's size in data units.
+   * Any dummy data units added to complete an MCU are not counted; therefore
+   * these values do not depend on whether a scan is interleaved or not.
+   */
+  JDIMENSION width_in_data_units;
+  JDIMENSION height_in_data_units;
+  /* Size of a data unit in/output by the codec (in samples).  Always
+   * data_unit for compression.  For decompression this is the size of the
+   * output from one data_unit, reflecting any processing performed by the
+   * codec.  For example, in the DCT-based codec, scaling may be applied
+   * during the IDCT step.  Values of 1,2,4,8 are likely to be supported.
+   * Note that different components may have different codec_data_unit sizes.
+   */
+  int codec_data_unit;
+  /* The downsampled dimensions are the component's actual, unpadded number
+   * of samples at the main buffer (preprocessing/compression interface), thus
+   * downsampled_width = ceil(image_width * Hi/Hmax)
+   * and similarly for height.  For decompression, codec-based processing is
+   * included (ie, IDCT scaling), so
+   * downsampled_width = ceil(image_width * Hi/Hmax * codec_data_unit/data_unit)
+   */
+  JDIMENSION downsampled_width;   /* actual width in samples */
+  JDIMENSION downsampled_height; /* actual height in samples */
+  /* This flag is used only for decompression.  In cases where some of the
+   * components will be ignored (eg grayscale output from YCbCr image),
+   * we can skip most computations for the unused components.
+   */
+  boolean component_needed;  /* do we need the value of this component? */
+
+  /* These values are computed before starting a scan of the component. */
+  /* The decompressor output side may not use these variables. */
+  int MCU_width;    /* number of data units per MCU, horizontally */
+  int MCU_height;    /* number of data units per MCU, vertically */
+  int MCU_data_units;    /* MCU_width * MCU_height */
+  int MCU_sample_width;    /* MCU width in samples, MCU_width*codec_data_unit */
+  int last_col_width;    /* # of non-dummy data_units across in last MCU */
+  int last_row_height;    /* # of non-dummy data_units down in last MCU */
+
+  /* Saved quantization table for component; NULL if none yet saved.
+   * See jdinput.c comments about the need for this information.
+   * This field is currently used only for decompression.
+   */
+  JQUANT_TBL * quant_table;
+
+  /* Private per-component storage for DCT or IDCT subsystem. */
+  void * dct_table;
+} jpeg_component_info;
+
+
+/* The script for encoding a multiple-scan file is an array of these: */
+
+typedef struct {
+  int comps_in_scan;    /* number of components encoded in this scan */
+  int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
+  int Ss, Se;      /* progressive JPEG spectral selection parms
+           lossless JPEG predictor select parm (Ss) */
+  int Ah, Al;      /* progressive JPEG successive approx. parms
+           lossless JPEG point transform parm (Al) */
+} jpeg_scan_info;
+
+/* The decompressor can save APPn and COM markers in a list of these: */
+
+typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr;
+
+struct jpeg_marker_struct {
+  jpeg_saved_marker_ptr next;  /* next in list, or NULL */
+  UINT8 marker;      /* marker code: JPEG_COM, or JPEG_APP0+n */
+  unsigned int original_length;  /* # bytes of data in the file */
+  unsigned int data_length;  /* # bytes of data saved at data[] */
+  JOCTET FAR * data;    /* the data contained in the marker */
+  /* the marker length word is not counted in data_length or original_length */
+};
+
+/* Known codec processes. */
+
+typedef enum {
+  JPROC_SEQUENTIAL,  /* baseline/extended sequential DCT */
+  JPROC_PROGRESSIVE,  /* progressive DCT */
+  JPROC_LOSSLESS    /* lossless (sequential) */
+} J_CODEC_PROCESS;
+
+/* Known color spaces. */
+
+typedef enum {
+  JCS_UNKNOWN,    /* error/unspecified */
+  JCS_GRAYSCALE,    /* monochrome */
+  JCS_RGB,    /* red/green/blue */
+  JCS_YCbCr,    /* Y/Cb/Cr (also known as YUV) */
+  JCS_CMYK,    /* C/M/Y/K */
+  JCS_YCCK    /* Y/Cb/Cr/K */
+} J_COLOR_SPACE;
+
+/* DCT/IDCT algorithm options. */
+
+typedef enum {
+  JDCT_ISLOW,    /* slow but accurate integer algorithm */
+  JDCT_IFAST,    /* faster, less accurate integer method */
+  JDCT_FLOAT    /* floating-point: accurate, fast on fast HW */
+} J_DCT_METHOD;
+
+#ifndef JDCT_DEFAULT    /* may be overridden in jconfig.h */
+#define JDCT_DEFAULT  JDCT_ISLOW
+#endif
+#ifndef JDCT_FASTEST    /* may be overridden in jconfig.h */
+#define JDCT_FASTEST  JDCT_IFAST
+#endif
+
+/* Dithering options for decompression. */
+
+typedef enum {
+  JDITHER_NONE,    /* no dithering */
+  JDITHER_ORDERED,  /* simple ordered dither */
+  JDITHER_FS    /* Floyd-Steinberg error diffusion dither */
+} J_DITHER_MODE;
+
+
+/* Common fields between JPEG compression and decompression master structs. */
+
+#define jpeg_common_fields \
+  struct jpeg_error_mgr * err;  /* Error handler module */\
+  struct jpeg_memory_mgr * mem;  /* Memory manager module */\
+  struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\
+  void * client_data;    /* Available for use by application */\
+  boolean is_decompressor;  /* So common code can tell which is which */\
+  int global_state    /* For checking call sequence validity */
+
+/* Routines that are to be used by both halves of the library are declared
+ * to receive a pointer to this structure.  There are no actual instances of
+ * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.
+ */
+struct jpeg_common_struct {
+  jpeg_common_fields;    /* Fields common to both master struct types */
+  /* Additional fields follow in an actual jpeg_compress_struct or
+   * jpeg_decompress_struct.  All three structs must agree on these
+   * initial fields!  (This would be a lot cleaner in C++.)
+   */
+};
+
+typedef struct jpeg_common_struct * j_common_ptr;
+typedef struct jpeg_compress_struct * j_compress_ptr;
+typedef struct jpeg_decompress_struct * j_decompress_ptr;
+
+
+/* Master record for a compression instance */
+
+struct jpeg_compress_struct {
+  jpeg_common_fields;    /* Fields shared with jpeg_decompress_struct */
+
+  /* Destination for compressed data */
+  struct jpeg_destination_mgr * dest;
+
+  /* Description of source image --- these fields must be filled in by
+   * outer application before starting compression.  in_color_space must
+   * be correct before you can even call jpeg_set_defaults().
+   */
+
+  JDIMENSION image_width;  /* input image width */
+  JDIMENSION image_height;  /* input image height */
+  int input_components;    /* # of color components in input image */
+  J_COLOR_SPACE in_color_space;  /* colorspace of input image */
+
+  double input_gamma;    /* image gamma of input image */
+
+  /* Compression parameters --- these fields must be set before calling
+   * jpeg_start_compress().  We recommend calling jpeg_set_defaults() to
+   * initialize everything to reasonable defaults, then changing anything
+   * the application specifically wants to change.  That way you won't get
+   * burnt when new parameters are added.  Also note that there are several
+   * helper routines to simplify changing parameters.
+   */
+
+  boolean lossless;    /* TRUE=lossless encoding, FALSE=lossy */
+
+  int data_precision;    /* bits of precision in image data */
+
+  int num_components;    /* # of color components in JPEG image */
+  J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
+
+  jpeg_component_info * comp_info;
+  /* comp_info[i] describes component that appears i'th in SOF */
+  
+  JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
+  /* ptrs to coefficient quantization tables, or NULL if not defined */
+  
+  JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+  JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+  /* ptrs to Huffman coding tables, or NULL if not defined */
+  
+  UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+  UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+  UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+  int num_scans;    /* # of entries in scan_info array */
+  const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */
+  /* The default value of scan_info is NULL, which causes a single-scan
+   * sequential JPEG file to be emitted.  To create a multi-scan file,
+   * set num_scans and scan_info to point to an array of scan definitions.
+   */
+
+  boolean raw_data_in;    /* TRUE=caller supplies downsampled data */
+  boolean arith_code;    /* TRUE=arithmetic coding, FALSE=Huffman */
+  boolean optimize_coding;  /* TRUE=optimize entropy encoding parms */
+  boolean CCIR601_sampling;  /* TRUE=first samples are cosited */
+  int smoothing_factor;    /* 1..100, or 0 for no input smoothing */
+  J_DCT_METHOD dct_method;  /* DCT algorithm selector */
+
+  /* The restart interval can be specified in absolute MCUs by setting
+   * restart_interval, or in MCU rows by setting restart_in_rows
+   * (in which case the correct restart_interval will be figured
+   * for each scan).
+   */
+  unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */
+  int restart_in_rows;    /* if > 0, MCU rows per restart interval */
+
+  /* Parameters controlling emission of special markers. */
+
+  boolean write_JFIF_header;  /* should a JFIF marker be written? */
+  UINT8 JFIF_major_version;  /* What to write for the JFIF version number */
+  UINT8 JFIF_minor_version;
+  /* These three values are not used by the JPEG code, merely copied */
+  /* into the JFIF APP0 marker.  density_unit can be 0 for unknown, */
+  /* 1 for dots/inch, or 2 for dots/cm.  Note that the pixel aspect */
+  /* ratio is defined by X_density/Y_density even when density_unit=0. */
+  UINT8 density_unit;    /* JFIF code for pixel size units */
+  UINT16 X_density;    /* Horizontal pixel density */
+  UINT16 Y_density;    /* Vertical pixel density */
+  boolean write_Adobe_marker;  /* should an Adobe marker be written? */
+  
+  /* State variable: index of next scanline to be written to
+   * jpeg_write_scanlines().  Application may use this to control its
+   * processing loop, e.g., "while (next_scanline < image_height)".
+   */
+
+  JDIMENSION next_scanline;  /* 0 .. image_height-1  */
+
+  /* Remaining fields are known throughout compressor, but generally
+   * should not be touched by a surrounding application.
+   */
+
+  /*
+   * These fields are computed during compression startup
+   */
+  int data_unit;    /* size of data unit in samples */
+  J_CODEC_PROCESS process;  /* encoding process of JPEG image */
+
+  int max_h_samp_factor;  /* largest h_samp_factor */
+  int max_v_samp_factor;  /* largest v_samp_factor */
+
+  JDIMENSION total_iMCU_rows;  /* # of iMCU rows to be input to codec */
+  /* The codec receives data in units of MCU rows as defined for fully
+   * interleaved scans (whether the JPEG file is interleaved or not).
+   * There are v_samp_factor * data_unit sample rows of each component in an
+   * "iMCU" (interleaved MCU) row.
+   */
+  
+  /*
+   * These fields are valid during any one scan.
+   * They describe the components and MCUs actually appearing in the scan.
+   */
+  int comps_in_scan;    /* # of JPEG components in this scan */
+  jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+  /* *cur_comp_info[i] describes component that appears i'th in SOS */
+  
+  JDIMENSION MCUs_per_row;  /* # of MCUs across the image */
+  JDIMENSION MCU_rows_in_scan;  /* # of MCU rows in the image */
+  
+  int data_units_in_MCU;  /* # of data units per MCU */
+  int MCU_membership[C_MAX_DATA_UNITS_IN_MCU];
+  /* MCU_membership[i] is index in cur_comp_info of component owning */
+  /* i'th block in an MCU */
+
+  int Ss, Se, Ah, Al;    /* progressive/lossless JPEG parameters for scan */
+
+  /*
+   * Links to compression subobjects (methods and private variables of modules)
+   */
+  struct jpeg_comp_master * master;
+  struct jpeg_c_main_controller * main;
+  struct jpeg_c_prep_controller * prep;
+  struct jpeg_c_codec * codec;
+  struct jpeg_marker_writer * marker;
+  struct jpeg_color_converter * cconvert;
+  struct jpeg_downsampler * downsample;
+  jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */
+  int script_space_size;
+};
+
+
+/* Master record for a decompression instance */
+
+struct jpeg_decompress_struct {
+  jpeg_common_fields;    /* Fields shared with jpeg_compress_struct */
+
+  /* Source of compressed data */
+  struct jpeg_source_mgr * src;
+
+  /* Basic description of image --- filled in by jpeg_read_header(). */
+  /* Application may inspect these values to decide how to process image. */
+
+  JDIMENSION image_width;  /* nominal image width (from SOF marker) */
+  JDIMENSION image_height;  /* nominal image height */
+  int num_components;    /* # of color components in JPEG image */
+  J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
+
+  /* Decompression processing parameters --- these fields must be set before
+   * calling jpeg_start_decompress().  Note that jpeg_read_header() initializes
+   * them to default values.
+   */
+
+  J_COLOR_SPACE out_color_space; /* colorspace for output */
+
+  unsigned int scale_num, scale_denom; /* fraction by which to scale image */
+
+  double output_gamma;    /* image gamma wanted in output */
+
+  boolean buffered_image;  /* TRUE=multiple output passes */
+  boolean raw_data_out;    /* TRUE=downsampled data wanted */
+
+  J_DCT_METHOD dct_method;  /* IDCT algorithm selector */
+  boolean do_fancy_upsampling;  /* TRUE=apply fancy upsampling */
+  boolean do_block_smoothing;  /* TRUE=apply interblock smoothing */
+
+  boolean quantize_colors;  /* TRUE=colormapped output wanted */
+  /* the following are ignored if not quantize_colors: */
+  J_DITHER_MODE dither_mode;  /* type of color dithering to use */
+  boolean two_pass_quantize;  /* TRUE=use two-pass color quantization */
+  int desired_number_of_colors;  /* max # colors to use in created colormap */
+  /* these are significant only in buffered-image mode: */
+  boolean enable_1pass_quant;  /* enable future use of 1-pass quantizer */
+  boolean enable_external_quant;/* enable future use of external colormap */
+  boolean enable_2pass_quant;  /* enable future use of 2-pass quantizer */
+
+  /* Description of actual output image that will be returned to application.
+   * These fields are computed by jpeg_start_decompress().
+   * You can also use jpeg_calc_output_dimensions() to determine these values
+   * in advance of calling jpeg_start_decompress().
+   */
+
+  JDIMENSION output_width;  /* scaled image width */
+  JDIMENSION output_height;  /* scaled image height */
+  int out_color_components;  /* # of color components in out_color_space */
+  int output_components;  /* # of color components returned */
+  /* output_components is 1 (a colormap index) when quantizing colors;
+   * otherwise it equals out_color_components.
+   */
+  int rec_outbuf_height;  /* min recommended height of scanline buffer */
+  /* If the buffer passed to jpeg_read_scanlines() is less than this many rows
+   * high, space and time will be wasted due to unnecessary data copying.
+   * Usually rec_outbuf_height will be 1 or 2, at most 4.
+   */
+
+  /* When quantizing colors, the output colormap is described by these fields.
+   * The application can supply a colormap by setting colormap non-NULL before
+   * calling jpeg_start_decompress; otherwise a colormap is created during
+   * jpeg_start_decompress or jpeg_start_output.
+   * The map has out_color_components rows and actual_number_of_colors columns.
+   */
+  int actual_number_of_colors;  /* number of entries in use */
+  JSAMPARRAY colormap;    /* The color map as a 2-D pixel array */
+
+  /* State variables: these variables indicate the progress of decompression.
+   * The application may examine these but must not modify them.
+   */
+
+  /* Row index of next scanline to be read from jpeg_read_scanlines().
+   * Application may use this to control its processing loop, e.g.,
+   * "while (output_scanline < output_height)".
+   */
+  JDIMENSION output_scanline;  /* 0 .. output_height-1  */
+
+  /* Current input scan number and number of iMCU rows completed in scan.
+   * These indicate the progress of the decompressor input side.
+   */
+  int input_scan_number;  /* Number of SOS markers seen so far */
+  JDIMENSION input_iMCU_row;  /* Number of iMCU rows completed */
+
+  /* The "output scan number" is the notional scan being displayed by the
+   * output side.  The decompressor will not allow output scan/row number
+   * to get ahead of input scan/row, but it can fall arbitrarily far behind.
+   */
+  int output_scan_number;  /* Nominal scan number being displayed */
+  JDIMENSION output_iMCU_row;  /* Number of iMCU rows read */
+
+  /* Current progression status.  coef_bits[c][i] indicates the precision
+   * with which component c's DCT coefficient i (in zigzag order) is known.
+   * It is -1 when no data has yet been received, otherwise it is the point
+   * transform (shift) value for the most recent scan of the coefficient
+   * (thus, 0 at completion of the progression).
+   * This pointer is NULL when reading a non-progressive file.
+   */
+  int (*coef_bits)[DCTSIZE2];  /* -1 or current Al value for each coef */
+
+  /* Internal JPEG parameters --- the application usually need not look at
+   * these fields.  Note that the decompressor output side may not use
+   * any parameters that can change between scans.
+   */
+
+  /* Quantization and Huffman tables are carried forward across input
+   * datastreams when processing abbreviated JPEG datastreams.
+   */
+
+  JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
+  /* ptrs to coefficient quantization tables, or NULL if not defined */
+
+  JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+  JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+  /* ptrs to Huffman coding tables, or NULL if not defined */
+
+  /* These parameters are never carried across datastreams, since they
+   * are given in SOF/SOS markers or defined to be reset by SOI.
+   */
+
+  int data_precision;    /* bits of precision in image data */
+
+  jpeg_component_info * comp_info;
+  /* comp_info[i] describes component that appears i'th in SOF */
+
+  boolean arith_code;    /* TRUE=arithmetic coding, FALSE=Huffman */
+
+  UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+  UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+  UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+  unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */
+
+  /* These fields record data obtained from optional markers recognized by
+   * the JPEG library.
+   */
+  boolean saw_JFIF_marker;  /* TRUE iff a JFIF APP0 marker was found */
+  /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */
+  UINT8 JFIF_major_version;  /* JFIF version number */
+  UINT8 JFIF_minor_version;
+  UINT8 density_unit;    /* JFIF code for pixel size units */
+  UINT16 X_density;    /* Horizontal pixel density */
+  UINT16 Y_density;    /* Vertical pixel density */
+  boolean saw_Adobe_marker;  /* TRUE iff an Adobe APP14 marker was found */
+  UINT8 Adobe_transform;  /* Color transform code from Adobe marker */
+
+  boolean CCIR601_sampling;  /* TRUE=first samples are cosited */
+
+  /* Aside from the specific data retained from APPn markers known to the
+   * library, the uninterpreted contents of any or all APPn and COM markers
+   * can be saved in a list for examination by the application.
+   */
+  jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */
+
+  /* Remaining fields are known throughout decompressor, but generally
+   * should not be touched by a surrounding application.
+   */
+
+  /*
+   * These fields are computed during decompression startup
+   */
+  int data_unit;    /* size of data unit in samples */
+  J_CODEC_PROCESS process;  /* decoding process of JPEG image */
+
+  int max_h_samp_factor;  /* largest h_samp_factor */
+  int max_v_samp_factor;  /* largest v_samp_factor */
+
+  int min_codec_data_unit;  /* smallest codec_data_unit of any component */
+
+  JDIMENSION total_iMCU_rows;  /* # of iMCU rows in image */
+  /* The codec's input and output progress is measured in units of "iMCU"
+   * (interleaved MCU) rows.  These are the same as MCU rows in fully
+   * interleaved JPEG scans, but are used whether the scan is interleaved
+   * or not.  We define an iMCU row as v_samp_factor data_unit rows of each
+   * component.  Therefore, the codec output contains
+   * v_samp_factor*codec_data_unit sample rows of a component per iMCU row.
+   */
+
+  JSAMPLE * sample_range_limit; /* table for fast range-limiting */
+
+  /*
+   * These fields are valid during any one scan.
+   * They describe the components and MCUs actually appearing in the scan.
+   * Note that the decompressor output side must not use these fields.
+   */
+  int comps_in_scan;    /* # of JPEG components in this scan */
+  jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+  /* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+  JDIMENSION MCUs_per_row;  /* # of MCUs across the image */
+  JDIMENSION MCU_rows_in_scan;  /* # of MCU rows in the image */
+
+  int data_units_in_MCU;  /* # of data _units per MCU */
+  int MCU_membership[D_MAX_DATA_UNITS_IN_MCU];
+  /* MCU_membership[i] is index in cur_comp_info of component owning */
+  /* i'th data unit in an MCU */
+
+  int Ss, Se, Ah, Al;    /* progressive/lossless JPEG parms for scan */
+
+  /* This field is shared between entropy decoder and marker parser.
+   * It is either zero or the code of a JPEG marker that has been
+   * read from the data source, but has not yet been processed.
+   */
+  int unread_marker;
+
+  /*
+   * Links to decompression subobjects (methods, private variables of modules)
+   */
+  struct jpeg_decomp_master * master;
+  struct jpeg_d_main_controller * main;
+  struct jpeg_d_codec * codec;
+  struct jpeg_d_post_controller * post;
+  struct jpeg_input_controller * inputctl;
+  struct jpeg_marker_reader * marker;
+  struct jpeg_upsampler * upsample;
+  struct jpeg_color_deconverter * cconvert;
+  struct jpeg_color_quantizer * cquantize;
+};
+
+
+/* "Object" declarations for JPEG modules that may be supplied or called
+ * directly by the surrounding application.
+ * As with all objects in the JPEG library, these structs only define the
+ * publicly visible methods and state variables of a module.  Additional
+ * private fields may exist after the public ones.
+ */
+
+
+/* Error handler object */
+
+struct jpeg_error_mgr {
+  /* Error exit handler: does not return to caller */
+  JMETHOD(void, error_exit, (j_common_ptr cinfo));
+  /* Conditionally emit a trace or warning message */
+  JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level));
+  /* Routine that actually outputs a trace or error message */
+  JMETHOD(void, output_message, (j_common_ptr cinfo));
+  /* Format a message string for the most recent JPEG error or message */
+  JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer));
+#define JMSG_LENGTH_MAX  200  /* recommended size of format_message buffer */
+  /* Reset error state variables at start of a new image */
+  JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo));
+  
+  /* The message ID code and any parameters are saved here.
+   * A message can have one string parameter or up to 8 int parameters.
+   */
+  int msg_code;
+#define JMSG_STR_PARM_MAX  80
+  union {
+    int i[8];
+    char s[JMSG_STR_PARM_MAX];
+  } msg_parm;
+  
+  /* Standard state variables for error facility */
+  
+  int trace_level;    /* max msg_level that will be displayed */
+  
+  /* For recoverable corrupt-data errors, we emit a warning message,
+   * but keep going unless emit_message chooses to abort.  emit_message
+   * should count warnings in num_warnings.  The surrounding application
+   * can check for bad data by seeing if num_warnings is nonzero at the
+   * end of processing.
+   */
+  long num_warnings;    /* number of corrupt-data warnings */
+
+  /* These fields point to the table(s) of error message strings.
+   * An application can change the table pointer to switch to a different
+   * message list (typically, to change the language in which errors are
+   * reported).  Some applications may wish to add additional error codes
+   * that will be handled by the JPEG library error mechanism; the second
+   * table pointer is used for this purpose.
+   *
+   * First table includes all errors generated by JPEG library itself.
+   * Error code 0 is reserved for a "no such error string" message.
+   */
+  const char * const * jpeg_message_table; /* Library errors */
+  int last_jpeg_message;    /* Table contains strings 0..last_jpeg_message */
+  /* Second table can be added by application (see cjpeg/djpeg for example).
+   * It contains strings numbered first_addon_message..last_addon_message.
+   */
+  const char * const * addon_message_table; /* Non-library errors */
+  int first_addon_message;  /* code for first string in addon table */
+  int last_addon_message;  /* code for last string in addon table */
+};
+
+
+/* Progress monitor object */
+
+struct jpeg_progress_mgr {
+  JMETHOD(void, progress_monitor, (j_common_ptr cinfo));
+
+  long pass_counter;    /* work units completed in this pass */
+  long pass_limit;    /* total number of work units in this pass */
+  int completed_passes;    /* passes completed so far */
+  int total_passes;    /* total number of passes expected */
+};
+
+
+/* Data destination object for compression */
+
+struct jpeg_destination_mgr {
+  JOCTET * next_output_byte;  /* => next byte to write in buffer */
+  size_t free_in_buffer;  /* # of byte spaces remaining in buffer */
+
+  JMETHOD(void, init_destination, (j_compress_ptr cinfo));
+  JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
+  JMETHOD(void, term_destination, (j_compress_ptr cinfo));
+};
+
+
+/* Data source object for decompression */
+
+struct jpeg_source_mgr {
+  const JOCTET * next_input_byte; /* => next byte to read from buffer */
+  size_t bytes_in_buffer;  /* # of bytes remaining in buffer */
+
+  JMETHOD(void, init_source, (j_decompress_ptr cinfo));
+  JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
+  JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
+  JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired));
+  JMETHOD(void, term_source, (j_decompress_ptr cinfo));
+};
+
+
+/* Memory manager object.
+ * Allocates "small" objects (a few K total), "large" objects (tens of K),
+ * and "really big" objects (virtual arrays with backing store if needed).
+ * The memory manager does not allow individual objects to be freed; rather,
+ * each created object is assigned to a pool, and whole pools can be freed
+ * at once.  This is faster and more convenient than remembering exactly what
+ * to free, especially where malloc()/free() are not too speedy.
+ * NB: alloc routines never return NULL.  They exit to error_exit if not
+ * successful.
+ */
+
+#define JPOOL_PERMANENT  0  /* lasts until master record is destroyed */
+#define JPOOL_IMAGE  1  /* lasts until done with image/datastream */
+#define JPOOL_NUMPOOLS  2
+
+typedef struct jvirt_sarray_control * jvirt_sarray_ptr;
+typedef struct jvirt_barray_control * jvirt_barray_ptr;
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+#define NEED_DARRAY
+#else
+#ifdef D_LOSSLESS_SUPPORTED
+#define NEED_DARRAY
+#endif
+#endif
+
+struct jpeg_memory_mgr {
+  /* Method pointers */
+  JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id,
+        size_t sizeofobject));
+  JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id,
+             size_t sizeofobject));
+  JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id,
+             JDIMENSION samplesperrow,
+             JDIMENSION numrows));
+  JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id,
+              JDIMENSION blocksperrow,
+              JDIMENSION numrows));
+#ifdef NEED_DARRAY
+  JMETHOD(JDIFFARRAY, alloc_darray, (j_common_ptr cinfo, int pool_id,
+             JDIMENSION diffsperrow,
+             JDIMENSION numrows));
+#endif
+  JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo,
+              int pool_id,
+              boolean pre_zero,
+              JDIMENSION samplesperrow,
+              JDIMENSION numrows,
+              JDIMENSION maxaccess));
+  JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo,
+              int pool_id,
+              boolean pre_zero,
+              JDIMENSION blocksperrow,
+              JDIMENSION numrows,
+              JDIMENSION maxaccess));
+  JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo));
+  JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo,
+             jvirt_sarray_ptr ptr,
+             JDIMENSION start_row,
+             JDIMENSION num_rows,
+             boolean writable));
+  JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo,
+              jvirt_barray_ptr ptr,
+              JDIMENSION start_row,
+              JDIMENSION num_rows,
+              boolean writable));
+  JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id));
+  JMETHOD(void, self_destruct, (j_common_ptr cinfo));
+
+  /* Limit on memory allocation for this JPEG object.  (Note that this is
+   * merely advisory, not a guaranteed maximum; it only affects the space
+   * used for virtual-array buffers.)  May be changed by outer application
+   * after creating the JPEG object.
+   */
+  long max_memory_to_use;
+
+  /* Maximum allocation request accepted by alloc_large. */
+  long max_alloc_chunk;
+};
+
+
+/* Routine signature for application-supplied marker processing methods.
+ * Need not pass marker code since it is stored in cinfo->unread_marker.
+ */
+typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo));
+
+
+/* Declarations for routines called by application.
+ * The JPP macro hides prototype parameters from compilers that can't cope.
+ * Note JPP requires double parentheses.
+ */
+
+#ifdef HAVE_PROTOTYPES
+#define JPP(arglist)  arglist
+#else
+#define JPP(arglist)  ()
+#endif
+
+
+/* Short forms of external names for systems with brain-damaged linkers.
+ * We shorten external names to be unique in the first six letters, which
+ * is good enough for all known systems.
+ * (If your compiler itself needs names to be unique in less than 15 
+ * characters, you are out of luck.  Get a better compiler.)
+ */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_std_error    jStdError
+#define jpeg_CreateCompress  jCreaCompress
+#define jpeg_CreateDecompress  jCreaDecompress
+#define jpeg_destroy_compress  jDestCompress
+#define jpeg_destroy_decompress  jDestDecompress
+#define jpeg_stdio_dest    jStdDest
+#define jpeg_stdio_src    jStdSrc
+#define jpeg_set_defaults  jSetDefaults
+#define jpeg_set_colorspace  jSetColorspace
+#define jpeg_default_colorspace  jDefColorspace
+#define jpeg_set_quality  jSetQuality
+#define jpeg_set_linear_quality  jSetLQuality
+#define jpeg_add_quant_table  jAddQuantTable
+#define jpeg_quality_scaling  jQualityScaling
+#define jpeg_simple_lossless  jSimLossless
+#define jpeg_simple_progression  jSimProgress
+#define jpeg_suppress_tables  jSuppressTables
+#define jpeg_alloc_quant_table  jAlcQTable
+#define jpeg_alloc_huff_table  jAlcHTable
+#define jpeg_start_compress  jStrtCompress
+#define jpeg_write_scanlines  jWrtScanlines
+#define jpeg_finish_compress  jFinCompress
+#define jpeg_write_raw_data  jWrtRawData
+#define jpeg_write_marker  jWrtMarker
+#define jpeg_write_m_header  jWrtMHeader
+#define jpeg_write_m_byte  jWrtMByte
+#define jpeg_write_tables  jWrtTables
+#define jpeg_read_header  jReadHeader
+#define jpeg_start_decompress  jStrtDecompress
+#define jpeg_read_scanlines  jReadScanlines
+#define jpeg_finish_decompress  jFinDecompress
+#define jpeg_read_raw_data  jReadRawData
+#define jpeg_has_multiple_scans  jHasMultScn
+#define jpeg_start_output  jStrtOutput
+#define jpeg_finish_output  jFinOutput
+#define jpeg_input_complete  jInComplete
+#define jpeg_new_colormap  jNewCMap
+#define jpeg_consume_input  jConsumeInput
+#define jpeg_calc_output_dimensions  jCalcDimensions
+#define jpeg_save_markers  jSaveMarkers
+#define jpeg_set_marker_processor  jSetMarker
+#define jpeg_read_coefficients  jReadCoefs
+#define jpeg_write_coefficients  jWrtCoefs
+#define jpeg_copy_critical_parameters  jCopyCrit
+#define jpeg_abort_compress  jAbrtCompress
+#define jpeg_abort_decompress  jAbrtDecompress
+#define jpeg_abort    jAbort
+#define jpeg_destroy    jDestroy
+#define jpeg_resync_to_restart  jResyncRestart
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Default error-management setup */
+EXTERN(struct jpeg_error_mgr *) jpeg_std_error
+  JPP((struct jpeg_error_mgr * err));
+
+/* Initialization of JPEG compression objects.
+ * jpeg_create_compress() and jpeg_create_decompress() are the exported
+ * names that applications should call.  These expand to calls on
+ * jpeg_CreateCompress and jpeg_CreateDecompress with additional information
+ * passed for version mismatch checking.
+ * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
+ */
+#define jpeg_create_compress(cinfo) \
+    jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
+      (size_t) sizeof(struct jpeg_compress_struct))
+#define jpeg_create_decompress(cinfo) \
+    jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
+        (size_t) sizeof(struct jpeg_decompress_struct))
+EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo,
+              int version, size_t structsize));
+EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo,
+          int version, size_t structsize));
+/* Destruction of JPEG compression objects */
+EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo));
+
+/* Standard data source and destination managers: stdio streams. */
+/* Caller is responsible for opening the file before and closing after. */
+EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile));
+EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));
+
+/* Default parameter setup for compression */
+EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo));
+/* Compression parameter setup aids */
+EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo,
+              J_COLOR_SPACE colorspace));
+EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality,
+           boolean force_baseline));
+EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo,
+            int scale_factor,
+            boolean force_baseline));
+EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl,
+               const unsigned int *basic_table,
+               int scale_factor,
+               boolean force_baseline));
+EXTERN(int) jpeg_quality_scaling JPP((int quality));
+EXTERN(void) jpeg_simple_lossless JPP((j_compress_ptr cinfo,
+               int predictor, int point_transform));
+EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo,
+               boolean suppress));
+EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo));
+EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo));
+
+/* Main entry points for compression */
+EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo,
+              boolean write_all_tables));
+EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo,
+               JSAMPARRAY scanlines,
+               JDIMENSION num_lines));
+EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo));
+
+/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
+EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo,
+              JSAMPIMAGE data,
+              JDIMENSION num_lines));
+
+/* Write a special marker.  See libjpeg.doc concerning safe usage. */
+EXTERN(void) jpeg_write_marker
+  JPP((j_compress_ptr cinfo, int marker,
+       const JOCTET * dataptr, unsigned int datalen));
+/* Same, but piecemeal. */
+EXTERN(void) jpeg_write_m_header
+  JPP((j_compress_ptr cinfo, int marker, unsigned int datalen));
+EXTERN(void) jpeg_write_m_byte
+  JPP((j_compress_ptr cinfo, int val));
+
+/* Alternate compression function: just write an abbreviated table file */
+EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo));
+
+/* Decompression startup: read start of JPEG datastream to see what's there */
+EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo,
+          boolean require_image));
+/* Return value is one of: */
+#define JPEG_SUSPENDED    0 /* Suspended due to lack of input data */
+#define JPEG_HEADER_OK    1 /* Found valid image datastream */
+#define JPEG_HEADER_TABLES_ONLY  2 /* Found valid table-specs-only datastream */
+/* If you pass require_image = TRUE (normal case), you need not check for
+ * a TABLES_ONLY return code; an abbreviated file will cause an error exit.
+ * JPEG_SUSPENDED is only possible if you use a data source module that can
+ * give a suspension return (the stdio source module doesn't).
+ */
+
+/* Main entry points for decompression */
+EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo));
+EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo,
+              JSAMPARRAY scanlines,
+              JDIMENSION max_lines));
+EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo));
+
+/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
+EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo,
+             JSAMPIMAGE data,
+             JDIMENSION max_lines));
+
+/* Additional entry points for buffered-image mode. */
+EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo));
+EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo,
+               int scan_number));
+EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo));
+EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo));
+EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo));
+EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo));
+/* Return value is one of: */
+/* #define JPEG_SUSPENDED  0    Suspended due to lack of input data */
+#define JPEG_REACHED_SOS  1 /* Reached start of new scan */
+#define JPEG_REACHED_EOI  2 /* Reached end of image */
+#define JPEG_ROW_COMPLETED  3 /* Completed one iMCU row */
+#define JPEG_SCAN_COMPLETED  4 /* Completed last iMCU row of a scan */
+
+/* Precalculate output dimensions for current decompression parameters. */
+EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo));
+
+/* Control saving of COM and APPn markers into marker_list. */
+EXTERN(void) jpeg_save_markers
+  JPP((j_decompress_ptr cinfo, int marker_code,
+       unsigned int length_limit));
+
+/* Install a special processing method for COM or APPn markers. */
+EXTERN(void) jpeg_set_marker_processor
+  JPP((j_decompress_ptr cinfo, int marker_code,
+       jpeg_marker_parser_method routine));
+
+/* Read or write raw DCT coefficients --- useful for lossless transcoding. */
+EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo));
+EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo,
+            jvirt_barray_ptr * coef_arrays));
+EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo,
+            j_compress_ptr dstinfo));
+
+/* If you choose to abort compression or decompression before completing
+ * jpeg_finish_(de)compress, then you need to clean up to release memory,
+ * temporary files, etc.  You can just call jpeg_destroy_(de)compress
+ * if you're done with the JPEG object, but if you want to clean it up and
+ * reuse it, call this:
+ */
+EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo));
+
+/* Generic versions of jpeg_abort and jpeg_destroy that work on either
+ * flavor of JPEG object.  These may be more convenient in some places.
+ */
+EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo));
+EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo));
+
+/* Default restart-marker-resync procedure for use by data source modules */
+EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo,
+              int desired));
+
+
+/* These marker codes are exported since applications and data source modules
+ * are likely to want to use them.
+ */
+
+#define JPEG_RST0  0xD0  /* RST0 marker code */
+#define JPEG_EOI  0xD9  /* EOI marker code */
+#define JPEG_APP0  0xE0  /* APP0 marker code */
+#define JPEG_COM  0xFE  /* COM marker code */
+
+
+/* If we have a brain-damaged compiler that emits warnings (or worse, errors)
+ * for structure definitions that are never filled in, keep it quiet by
+ * supplying dummy definitions for the various substructures.
+ */
+
+#ifdef INCOMPLETE_TYPES_BROKEN
+#ifndef JPEG_INTERNALS    /* will be defined in jpegint.h */
+struct jvirt_sarray_control { long dummy; };
+struct jvirt_barray_control { long dummy; };
+struct jpeg_comp_master { long dummy; };
+struct jpeg_c_main_controller { long dummy; };
+struct jpeg_c_prep_controller { long dummy; };
+struct jpeg_c_coef_controller { long dummy; };
+struct jpeg_marker_writer { long dummy; };
+struct jpeg_color_converter { long dummy; };
+struct jpeg_downsampler { long dummy; };
+struct jpeg_forward_dct { long dummy; };
+struct jpeg_entropy_encoder { long dummy; };
+struct jpeg_decomp_master { long dummy; };
+struct jpeg_d_main_controller { long dummy; };
+struct jpeg_d_coef_controller { long dummy; };
+struct jpeg_d_post_controller { long dummy; };
+struct jpeg_input_controller { long dummy; };
+struct jpeg_marker_reader { long dummy; };
+struct jpeg_entropy_decoder { long dummy; };
+struct jpeg_inverse_dct { long dummy; };
+struct jpeg_upsampler { long dummy; };
+struct jpeg_color_deconverter { long dummy; };
+struct jpeg_color_quantizer { long dummy; };
+#endif /* JPEG_INTERNALS */
+#endif /* INCOMPLETE_TYPES_BROKEN */
+
+
+/*
+ * The JPEG library modules define JPEG_INTERNALS before including this file.
+ * The internal structure declarations are read only when that is true.
+ * Applications using the library should not include jpegint.h, but may wish
+ * to include jerror.h.
+ */
+
+#ifdef JPEG_INTERNALS
+#include "jpegint.h"    /* fetch private declarations */
+#include "jerror.h"    /* fetch error codes too */
+#endif
+
+#endif /* JPEGLIB_H */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jquant1.c b/Utilities/ITK/Utilities/itkjpeg/jquant1.c
new file mode 100644
index 0000000000000000000000000000000000000000..a5abd0a8bd500bf4c55ab03cdbf08d16e34b2221
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jquant1.c
@@ -0,0 +1,860 @@
+/*
+ * jquant1.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains 1-pass color quantization (color mapping) routines.
+ * These routines provide mapping to a fixed color map using equally spaced
+ * color values.  Optional Floyd-Steinberg or ordered dithering is available.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+#ifdef QUANT_1PASS_SUPPORTED
+
+
+/*
+ * The main purpose of 1-pass quantization is to provide a fast, if not very
+ * high quality, colormapped output capability.  A 2-pass quantizer usually
+ * gives better visual quality; however, for quantized grayscale output this
+ * quantizer is perfectly adequate.  Dithering is highly recommended with this
+ * quantizer, though you can turn it off if you really want to.
+ *
+ * In 1-pass quantization the colormap must be chosen in advance of seeing the
+ * image.  We use a map consisting of all combinations of Ncolors[i] color
+ * values for the i'th component.  The Ncolors[] values are chosen so that
+ * their product, the total number of colors, is no more than that requested.
+ * (In most cases, the product will be somewhat less.)
+ *
+ * Since the colormap is orthogonal, the representative value for each color
+ * component can be determined without considering the other components;
+ * then these indexes can be combined into a colormap index by a standard
+ * N-dimensional-array-subscript calculation.  Most of the arithmetic involved
+ * can be precalculated and stored in the lookup table colorindex[].
+ * colorindex[i][j] maps pixel value j in component i to the nearest
+ * representative value (grid plane) for that component; this index is
+ * multiplied by the array stride for component i, so that the
+ * index of the colormap entry closest to a given pixel value is just
+ *    sum( colorindex[component-number][pixel-component-value] )
+ * Aside from being fast, this scheme allows for variable spacing between
+ * representative values with no additional lookup cost.
+ *
+ * If gamma correction has been applied in color conversion, it might be wise
+ * to adjust the color grid spacing so that the representative colors are
+ * equidistant in linear space.  At this writing, gamma correction is not
+ * implemented by jdcolor, so nothing is done here.
+ */
+
+
+/* Declarations for ordered dithering.
+ *
+ * We use a standard 16x16 ordered dither array.  The basic concept of ordered
+ * dithering is described in many references, for instance Dale Schumacher's
+ * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991).
+ * In place of Schumacher's comparisons against a "threshold" value, we add a
+ * "dither" value to the input pixel and then round the result to the nearest
+ * output value.  The dither value is equivalent to (0.5 - threshold) times
+ * the distance between output values.  For ordered dithering, we assume that
+ * the output colors are equally spaced; if not, results will probably be
+ * worse, since the dither may be too much or too little at a given point.
+ *
+ * The normal calculation would be to form pixel value + dither, range-limit
+ * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual.
+ * We can skip the separate range-limiting step by extending the colorindex
+ * table in both directions.
+ */
+
+#define ODITHER_SIZE  16  /* dimension of dither matrix */
+/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */
+#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE)  /* # cells in matrix */
+#define ODITHER_MASK  (ODITHER_SIZE-1) /* mask for wrapping around counters */
+
+typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE];
+typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE];
+
+static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = {
+  /* Bayer's order-4 dither array.  Generated by the code given in
+   * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I.
+   * The values in this array must range from 0 to ODITHER_CELLS-1.
+   */
+  {   0,192, 48,240, 12,204, 60,252,  3,195, 51,243, 15,207, 63,255 },
+  { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
+  {  32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
+  { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
+  {   8,200, 56,248,  4,196, 52,244, 11,203, 59,251,  7,199, 55,247 },
+  { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
+  {  40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
+  { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
+  {   2,194, 50,242, 14,206, 62,254,  1,193, 49,241, 13,205, 61,253 },
+  { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
+  {  34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
+  { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
+  {  10,202, 58,250,  6,198, 54,246,  9,201, 57,249,  5,197, 53,245 },
+  { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
+  {  42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
+  { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
+};
+
+
+/* Declarations for Floyd-Steinberg dithering.
+ *
+ * Errors are accumulated into the array fserrors[], at a resolution of
+ * 1/16th of a pixel count.  The error at a given pixel is propagated
+ * to its not-yet-processed neighbors using the standard F-S fractions,
+ *    ...  (here)  7/16
+ *    3/16  5/16  1/16
+ * We work left-to-right on even rows, right-to-left on odd rows.
+ *
+ * We can get away with a single array (holding one row's worth of errors)
+ * by using it to store the current row's errors at pixel columns not yet
+ * processed, but the next row's errors at columns already processed.  We
+ * need only a few extra variables to hold the errors immediately around the
+ * current column.  (If we are lucky, those variables are in registers, but
+ * even if not, they're probably cheaper to access than array elements are.)
+ *
+ * The fserrors[] array is indexed [component#][position].
+ * We provide (#columns + 2) entries per component; the extra entry at each
+ * end saves us from special-casing the first and last pixels.
+ *
+ * Note: on a wide image, we might not have enough room in a PC's near data
+ * segment to hold the error array; so it is allocated with alloc_large.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef INT16 FSERROR;    /* 16 bits should be enough */
+typedef int LOCFSERROR;    /* use 'int' for calculation temps */
+#else
+typedef INT32 FSERROR;    /* may need more than 16 bits */
+typedef INT32 LOCFSERROR;  /* be sure calculation temps are big enough */
+#endif
+
+typedef FSERROR FAR *FSERRPTR;  /* pointer to error array (in FAR storage!) */
+
+
+/* Private subobject */
+
+#define MAX_Q_COMPS 4    /* max components I can handle */
+
+typedef struct {
+  struct jpeg_color_quantizer pub; /* public fields */
+
+  /* Initially allocated colormap is saved here */
+  JSAMPARRAY sv_colormap;  /* The color map as a 2-D pixel array */
+  int sv_actual;    /* number of entries in use */
+
+  JSAMPARRAY colorindex;  /* Precomputed mapping for speed */
+  /* colorindex[i][j] = index of color closest to pixel value j in component i,
+   * premultiplied as described above.  Since colormap indexes must fit into
+   * JSAMPLEs, the entries of this array will too.
+   */
+  boolean is_padded;    /* is the colorindex padded for odither? */
+
+  int Ncolors[MAX_Q_COMPS];  /* # of values alloced to each component */
+
+  /* Variables for ordered dithering */
+  int row_index;    /* cur row's vertical index in dither matrix */
+  ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */
+
+  /* Variables for Floyd-Steinberg dithering */
+  FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */
+  boolean on_odd_row;    /* flag to remember which row we are on */
+} my_cquantizer;
+
+typedef my_cquantizer * my_cquantize_ptr;
+
+
+/*
+ * Policy-making subroutines for create_colormap and create_colorindex.
+ * These routines determine the colormap to be used.  The rest of the module
+ * only assumes that the colormap is orthogonal.
+ *
+ *  * select_ncolors decides how to divvy up the available colors
+ *    among the components.
+ *  * output_value defines the set of representative values for a component.
+ *  * largest_input_value defines the mapping from input values to
+ *    representative values for a component.
+ * Note that the latter two routines may impose different policies for
+ * different components, though this is not currently done.
+ */
+
+
+LOCAL(int)
+select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
+/* Determine allocation of desired colors to components, */
+/* and fill in Ncolors[] array to indicate choice. */
+/* Return value is total number of colors (product of Ncolors[] values). */
+{
+  int nc = cinfo->out_color_components; /* number of color components */
+  int max_colors = cinfo->desired_number_of_colors;
+  int total_colors, iroot, i, j;
+  boolean changed;
+  long temp;
+  static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE };
+
+  /* We can allocate at least the nc'th root of max_colors per component. */
+  /* Compute floor(nc'th root of max_colors). */
+  iroot = 1;
+  do {
+    iroot++;
+    temp = iroot;    /* set temp = iroot ** nc */
+    for (i = 1; i < nc; i++)
+      temp *= iroot;
+  } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */
+  iroot--;      /* now iroot = floor(root) */
+
+  /* Must have at least 2 color values per component */
+  if (iroot < 2)
+    ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp);
+
+  /* Initialize to iroot color values for each component */
+  total_colors = 1;
+  for (i = 0; i < nc; i++) {
+    Ncolors[i] = iroot;
+    total_colors *= iroot;
+  }
+  /* We may be able to increment the count for one or more components without
+   * exceeding max_colors, though we know not all can be incremented.
+   * Sometimes, the first component can be incremented more than once!
+   * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.)
+   * In RGB colorspace, try to increment G first, then R, then B.
+   */
+  do {
+    changed = FALSE;
+    for (i = 0; i < nc; i++) {
+      j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i);
+      /* calculate new total_colors if Ncolors[j] is incremented */
+      temp = total_colors / Ncolors[j];
+      temp *= Ncolors[j]+1;  /* done in long arith to avoid oflo */
+      if (temp > (long) max_colors)
+  break;      /* won't fit, done with this pass */
+      Ncolors[j]++;    /* OK, apply the increment */
+      total_colors = (int) temp;
+      changed = TRUE;
+    }
+  } while (changed);
+
+  return total_colors;
+}
+
+
+LOCAL(int)
+output_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+/* Return j'th output value, where j will range from 0 to maxj */
+/* The output values must fall in 0..MAXJSAMPLE in increasing order */
+{
+  (void)cinfo;(void)ci;
+  /* We always provide values 0 and MAXJSAMPLE for each component;
+   * any additional values are equally spaced between these limits.
+   * (Forcing the upper and lower values to the limits ensures that
+   * dithering can't produce a color outside the selected gamut.)
+   */
+  return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj);
+}
+
+
+LOCAL(int)
+largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+/* Return largest input value that should map to j'th output value */
+/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */
+{
+  (void)cinfo;(void)ci;
+  /* Breakpoints are halfway between values returned by output_value */
+  return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj));
+}
+
+
+/*
+ * Create the colormap.
+ */
+
+LOCAL(void)
+create_colormap (j_decompress_ptr cinfo)
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  JSAMPARRAY colormap;    /* Created colormap */
+  int total_colors;    /* Number of distinct output colors */
+  int i,j,k, nci, blksize, blkdist, ptr, val;
+
+  /* Select number of colors for each component */
+  total_colors = select_ncolors(cinfo, cquantize->Ncolors);
+
+  /* Report selected color counts */
+  if (cinfo->out_color_components == 3)
+    TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS,
+       total_colors, cquantize->Ncolors[0],
+       cquantize->Ncolors[1], cquantize->Ncolors[2]);
+  else
+    TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors);
+
+  /* Allocate and fill in the colormap. */
+  /* The colors are ordered in the map in standard row-major order, */
+  /* i.e. rightmost (highest-indexed) color changes most rapidly. */
+
+  colormap = (*cinfo->mem->alloc_sarray)
+    ((j_common_ptr) cinfo, JPOOL_IMAGE,
+     (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components);
+
+  /* blksize is number of adjacent repeated entries for a component */
+  /* blkdist is distance between groups of identical entries for a component */
+  blkdist = total_colors;
+
+  for (i = 0; i < cinfo->out_color_components; i++) {
+    /* fill in colormap entries for i'th color component */
+    nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+    blksize = blkdist / nci;
+    for (j = 0; j < nci; j++) {
+      /* Compute j'th output value (out of nci) for component */
+      val = output_value(cinfo, i, j, nci-1);
+      /* Fill in all colormap entries that have this value of this component */
+      for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
+  /* fill in blksize entries beginning at ptr */
+  for (k = 0; k < blksize; k++)
+    colormap[i][ptr+k] = (JSAMPLE) val;
+      }
+    }
+    blkdist = blksize;    /* blksize of this color is blkdist of next */
+  }
+
+  /* Save the colormap in private storage,
+   * where it will survive color quantization mode changes.
+   */
+  cquantize->sv_colormap = colormap;
+  cquantize->sv_actual = total_colors;
+}
+
+
+/*
+ * Create the color index table.
+ */
+
+LOCAL(void)
+create_colorindex (j_decompress_ptr cinfo)
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  JSAMPROW indexptr;
+  int i,j,k, nci, blksize, val, pad;
+
+  /* For ordered dither, we pad the color index tables by MAXJSAMPLE in
+   * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE).
+   * This is not necessary in the other dithering modes.  However, we
+   * flag whether it was done in case user changes dithering mode.
+   */
+  if (cinfo->dither_mode == JDITHER_ORDERED) {
+    pad = MAXJSAMPLE*2;
+    cquantize->is_padded = TRUE;
+  } else {
+    pad = 0;
+    cquantize->is_padded = FALSE;
+  }
+
+  cquantize->colorindex = (*cinfo->mem->alloc_sarray)
+    ((j_common_ptr) cinfo, JPOOL_IMAGE,
+     (JDIMENSION) (MAXJSAMPLE+1 + pad),
+     (JDIMENSION) cinfo->out_color_components);
+
+  /* blksize is number of adjacent repeated entries for a component */
+  blksize = cquantize->sv_actual;
+
+  for (i = 0; i < cinfo->out_color_components; i++) {
+    /* fill in colorindex entries for i'th color component */
+    nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+    blksize = blksize / nci;
+
+    /* adjust colorindex pointers to provide padding at negative indexes. */
+    if (pad)
+      cquantize->colorindex[i] += MAXJSAMPLE;
+
+    /* in loop, val = index of current output value, */
+    /* and k = largest j that maps to current val */
+    indexptr = cquantize->colorindex[i];
+    val = 0;
+    k = largest_input_value(cinfo, i, 0, nci-1);
+    for (j = 0; j <= MAXJSAMPLE; j++) {
+      while (j > k)    /* advance val if past boundary */
+  k = largest_input_value(cinfo, i, ++val, nci-1);
+      /* premultiply so that no multiplication needed in main processing */
+      indexptr[j] = (JSAMPLE) (val * blksize);
+    }
+    /* Pad at both ends if necessary */
+    if (pad)
+      for (j = 1; j <= MAXJSAMPLE; j++) {
+  indexptr[-j] = indexptr[0];
+  indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE];
+      }
+  }
+}
+
+
+/*
+ * Create an ordered-dither array for a component having ncolors
+ * distinct output values.
+ */
+
+LOCAL(ODITHER_MATRIX_PTR)
+make_odither_array (j_decompress_ptr cinfo, int ncolors)
+{
+  ODITHER_MATRIX_PTR odither;
+  int j,k;
+  INT32 num,den;
+
+  odither = (ODITHER_MATRIX_PTR)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(ODITHER_MATRIX));
+  /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1).
+   * Hence the dither value for the matrix cell with fill order f
+   * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1).
+   * On 16-bit-int machine, be careful to avoid overflow.
+   */
+  den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1));
+  for (j = 0; j < ODITHER_SIZE; j++) {
+    for (k = 0; k < ODITHER_SIZE; k++) {
+      num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k])))
+      * MAXJSAMPLE;
+      /* Ensure round towards zero despite C's lack of consistency
+       * about rounding negative values in integer division...
+       */
+      odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den);
+    }
+  }
+  return odither;
+}
+
+
+/*
+ * Create the ordered-dither tables.
+ * Components having the same number of representative colors may 
+ * share a dither table.
+ */
+
+LOCAL(void)
+create_odither_tables (j_decompress_ptr cinfo)
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  ODITHER_MATRIX_PTR odither;
+  int i, j, nci;
+
+  for (i = 0; i < cinfo->out_color_components; i++) {
+    nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+    odither = NULL;    /* search for matching prior component */
+    for (j = 0; j < i; j++) {
+      if (nci == cquantize->Ncolors[j]) {
+  odither = cquantize->odither[j];
+  break;
+      }
+    }
+    if (odither == NULL)  /* need a new table? */
+      odither = make_odither_array(cinfo, nci);
+    cquantize->odither[i] = odither;
+  }
+}
+
+
+/*
+ * Map some rows of pixels to the output colormapped representation.
+ */
+
+METHODDEF(void)
+color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+    JSAMPARRAY output_buf, int num_rows)
+/* General case, no dithering */
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  JSAMPARRAY colorindex = cquantize->colorindex;
+  register int pixcode, ci;
+  register JSAMPROW ptrin, ptrout;
+  int row;
+  JDIMENSION col;
+  JDIMENSION width = cinfo->output_width;
+  register int nc = cinfo->out_color_components;
+
+  for (row = 0; row < num_rows; row++) {
+    ptrin = input_buf[row];
+    ptrout = output_buf[row];
+    for (col = width; col > 0; col--) {
+      pixcode = 0;
+      for (ci = 0; ci < nc; ci++) {
+  pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
+      }
+      *ptrout++ = (JSAMPLE) pixcode;
+    }
+  }
+}
+
+
+METHODDEF(void)
+color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+     JSAMPARRAY output_buf, int num_rows)
+/* Fast path for out_color_components==3, no dithering */
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  register int pixcode;
+  register JSAMPROW ptrin, ptrout;
+  JSAMPROW colorindex0 = cquantize->colorindex[0];
+  JSAMPROW colorindex1 = cquantize->colorindex[1];
+  JSAMPROW colorindex2 = cquantize->colorindex[2];
+  int row;
+  JDIMENSION col;
+  JDIMENSION width = cinfo->output_width;
+
+  for (row = 0; row < num_rows; row++) {
+    ptrin = input_buf[row];
+    ptrout = output_buf[row];
+    for (col = width; col > 0; col--) {
+      pixcode  = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]);
+      pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
+      pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
+      *ptrout++ = (JSAMPLE) pixcode;
+    }
+  }
+}
+
+
+METHODDEF(void)
+quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+         JSAMPARRAY output_buf, int num_rows)
+/* General case, with ordered dithering */
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  register JSAMPROW input_ptr;
+  register JSAMPROW output_ptr;
+  JSAMPROW colorindex_ci;
+  int * dither;      /* points to active row of dither matrix */
+  int row_index, col_index;  /* current indexes into dither matrix */
+  int nc = cinfo->out_color_components;
+  int ci;
+  int row;
+  JDIMENSION col;
+  JDIMENSION width = cinfo->output_width;
+
+  for (row = 0; row < num_rows; row++) {
+    /* Initialize output values to 0 so can process components separately */
+    jzero_far((void FAR *) output_buf[row],
+        (size_t) (width * SIZEOF(JSAMPLE)));
+    row_index = cquantize->row_index;
+    for (ci = 0; ci < nc; ci++) {
+      input_ptr = input_buf[row] + ci;
+      output_ptr = output_buf[row];
+      colorindex_ci = cquantize->colorindex[ci];
+      dither = cquantize->odither[ci][row_index];
+      col_index = 0;
+
+      for (col = width; col > 0; col--) {
+  /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE,
+   * select output value, accumulate into output code for this pixel.
+   * Range-limiting need not be done explicitly, as we have extended
+   * the colorindex table to produce the right answers for out-of-range
+   * inputs.  The maximum dither is +- MAXJSAMPLE; this sets the
+   * required amount of padding.
+   */
+  *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]];
+  input_ptr += nc;
+  output_ptr++;
+  col_index = (col_index + 1) & ODITHER_MASK;
+      }
+    }
+    /* Advance row index for next row */
+    row_index = (row_index + 1) & ODITHER_MASK;
+    cquantize->row_index = row_index;
+  }
+}
+
+
+METHODDEF(void)
+quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+          JSAMPARRAY output_buf, int num_rows)
+/* Fast path for out_color_components==3, with ordered dithering */
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  register int pixcode;
+  register JSAMPROW input_ptr;
+  register JSAMPROW output_ptr;
+  JSAMPROW colorindex0 = cquantize->colorindex[0];
+  JSAMPROW colorindex1 = cquantize->colorindex[1];
+  JSAMPROW colorindex2 = cquantize->colorindex[2];
+  int * dither0;    /* points to active row of dither matrix */
+  int * dither1;
+  int * dither2;
+  int row_index, col_index;  /* current indexes into dither matrix */
+  int row;
+  JDIMENSION col;
+  JDIMENSION width = cinfo->output_width;
+
+  for (row = 0; row < num_rows; row++) {
+    row_index = cquantize->row_index;
+    input_ptr = input_buf[row];
+    output_ptr = output_buf[row];
+    dither0 = cquantize->odither[0][row_index];
+    dither1 = cquantize->odither[1][row_index];
+    dither2 = cquantize->odither[2][row_index];
+    col_index = 0;
+
+    for (col = width; col > 0; col--) {
+      pixcode  = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) +
+          dither0[col_index]]);
+      pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) +
+          dither1[col_index]]);
+      pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) +
+          dither2[col_index]]);
+      *output_ptr++ = (JSAMPLE) pixcode;
+      col_index = (col_index + 1) & ODITHER_MASK;
+    }
+    row_index = (row_index + 1) & ODITHER_MASK;
+    cquantize->row_index = row_index;
+  }
+}
+
+
+METHODDEF(void)
+quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+        JSAMPARRAY output_buf, int num_rows)
+/* General case, with Floyd-Steinberg dithering */
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  register LOCFSERROR cur;  /* current error or pixel value */
+  LOCFSERROR belowerr;    /* error for pixel below cur */
+  LOCFSERROR bpreverr;    /* error for below/prev col */
+  LOCFSERROR bnexterr;    /* error for below/next col */
+  LOCFSERROR delta;
+  register FSERRPTR errorptr;  /* => fserrors[] at column before current */
+  register JSAMPROW input_ptr;
+  register JSAMPROW output_ptr;
+  JSAMPROW colorindex_ci;
+  JSAMPROW colormap_ci;
+  int pixcode;
+  int nc = cinfo->out_color_components;
+  int dir;      /* 1 for left-to-right, -1 for right-to-left */
+  int dirnc;      /* dir * nc */
+  int ci;
+  int row;
+  JDIMENSION col;
+  JDIMENSION width = cinfo->output_width;
+  JSAMPLE *range_limit = cinfo->sample_range_limit;
+  SHIFT_TEMPS
+
+  for (row = 0; row < num_rows; row++) {
+    /* Initialize output values to 0 so can process components separately */
+    jzero_far((void FAR *) output_buf[row],
+        (size_t) (width * SIZEOF(JSAMPLE)));
+    for (ci = 0; ci < nc; ci++) {
+      input_ptr = input_buf[row] + ci;
+      output_ptr = output_buf[row];
+      if (cquantize->on_odd_row) {
+  /* work right to left in this row */
+  input_ptr += (width-1) * nc; /* so point to rightmost pixel */
+  output_ptr += width-1;
+  dir = -1;
+  dirnc = -nc;
+  errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */
+      } else {
+  /* work left to right in this row */
+  dir = 1;
+  dirnc = nc;
+  errorptr = cquantize->fserrors[ci]; /* => entry before first column */
+      }
+      colorindex_ci = cquantize->colorindex[ci];
+      colormap_ci = cquantize->sv_colormap[ci];
+      /* Preset error values: no error propagated to first pixel from left */
+      cur = 0;
+      /* and no error propagated to row below yet */
+      belowerr = bpreverr = 0;
+
+      for (col = width; col > 0; col--) {
+  /* cur holds the error propagated from the previous pixel on the
+   * current line.  Add the error propagated from the previous line
+   * to form the complete error correction term for this pixel, and
+   * round the error term (which is expressed * 16) to an integer.
+   * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
+   * for either sign of the error value.
+   * Note: errorptr points to *previous* column's array entry.
+   */
+  cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4);
+  /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
+   * The maximum error is +- MAXJSAMPLE; this sets the required size
+   * of the range_limit array.
+   */
+  cur += GETJSAMPLE(*input_ptr);
+  cur = GETJSAMPLE(range_limit[cur]);
+  /* Select output value, accumulate into output code for this pixel */
+  pixcode = GETJSAMPLE(colorindex_ci[cur]);
+  *output_ptr += (JSAMPLE) pixcode;
+  /* Compute actual representation error at this pixel */
+  /* Note: we can do this even though we don't have the final */
+  /* pixel code, because the colormap is orthogonal. */
+  cur -= GETJSAMPLE(colormap_ci[pixcode]);
+  /* Compute error fractions to be propagated to adjacent pixels.
+   * Add these into the running sums, and simultaneously shift the
+   * next-line error sums left by 1 column.
+   */
+  bnexterr = cur;
+  delta = cur * 2;
+  cur += delta;    /* form error * 3 */
+  errorptr[0] = (FSERROR) (bpreverr + cur);
+  cur += delta;    /* form error * 5 */
+  bpreverr = belowerr + cur;
+  belowerr = bnexterr;
+  cur += delta;    /* form error * 7 */
+  /* At this point cur contains the 7/16 error value to be propagated
+   * to the next pixel on the current line, and all the errors for the
+   * next line have been shifted over. We are therefore ready to move on.
+   */
+  input_ptr += dirnc;  /* advance input ptr to next column */
+  output_ptr += dir;  /* advance output ptr to next column */
+  errorptr += dir;  /* advance errorptr to current column */
+      }
+      /* Post-loop cleanup: we must unload the final error value into the
+       * final fserrors[] entry.  Note we need not unload belowerr because
+       * it is for the dummy column before or after the actual array.
+       */
+      errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */
+    }
+    cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE);
+  }
+}
+
+
+/*
+ * Allocate workspace for Floyd-Steinberg errors.
+ */
+
+LOCAL(void)
+alloc_fs_workspace (j_decompress_ptr cinfo)
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  size_t arraysize;
+  int i;
+
+  arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
+  for (i = 0; i < cinfo->out_color_components; i++) {
+    cquantize->fserrors[i] = (FSERRPTR)
+      (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+  }
+}
+
+
+/*
+ * Initialize for one-pass color quantization.
+ */
+
+METHODDEF(void)
+start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  size_t arraysize;
+  int i;
+  (void)is_pre_scan;
+
+  /* Install my colormap. */
+  cinfo->colormap = cquantize->sv_colormap;
+  cinfo->actual_number_of_colors = cquantize->sv_actual;
+
+  /* Initialize for desired dithering mode. */
+  switch (cinfo->dither_mode) {
+  case JDITHER_NONE:
+    if (cinfo->out_color_components == 3)
+      cquantize->pub.color_quantize = color_quantize3;
+    else
+      cquantize->pub.color_quantize = color_quantize;
+    break;
+  case JDITHER_ORDERED:
+    if (cinfo->out_color_components == 3)
+      cquantize->pub.color_quantize = quantize3_ord_dither;
+    else
+      cquantize->pub.color_quantize = quantize_ord_dither;
+    cquantize->row_index = 0;  /* initialize state for ordered dither */
+    /* If user changed to ordered dither from another mode,
+     * we must recreate the color index table with padding.
+     * This will cost extra space, but probably isn't very likely.
+     */
+    if (! cquantize->is_padded)
+      create_colorindex(cinfo);
+    /* Create ordered-dither tables if we didn't already. */
+    if (cquantize->odither[0] == NULL)
+      create_odither_tables(cinfo);
+    break;
+  case JDITHER_FS:
+    cquantize->pub.color_quantize = quantize_fs_dither;
+    cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */
+    /* Allocate Floyd-Steinberg workspace if didn't already. */
+    if (cquantize->fserrors[0] == NULL)
+      alloc_fs_workspace(cinfo);
+    /* Initialize the propagated errors to zero. */
+    arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
+    for (i = 0; i < cinfo->out_color_components; i++)
+      jzero_far((void FAR *) cquantize->fserrors[i], arraysize);
+    break;
+  default:
+    ERREXIT(cinfo, JERR_NOT_COMPILED);
+    break;
+  }
+}
+
+
+/*
+ * Finish up at the end of the pass.
+ */
+
+METHODDEF(void)
+finish_pass_1_quant (j_decompress_ptr cinfo)
+{
+  (void)cinfo;
+  /* no work in 1-pass case */
+}
+
+
+/*
+ * Switch to a new external colormap between output passes.
+ * Shouldn't get to this module!
+ */
+
+METHODDEF(void)
+new_color_map_1_quant (j_decompress_ptr cinfo)
+{
+  ERREXIT(cinfo, JERR_MODE_CHANGE);
+}
+
+
+/*
+ * Module initialization routine for 1-pass color quantization.
+ */
+
+GLOBAL(void)
+jinit_1pass_quantizer (j_decompress_ptr cinfo)
+{
+  my_cquantize_ptr cquantize;
+
+  cquantize = (my_cquantize_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_cquantizer));
+  cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+  cquantize->pub.start_pass = start_pass_1_quant;
+  cquantize->pub.finish_pass = finish_pass_1_quant;
+  cquantize->pub.new_color_map = new_color_map_1_quant;
+  cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */
+  cquantize->odither[0] = NULL;  /* Also flag odither arrays not allocated */
+
+  /* Make sure my internal arrays won't overflow */
+  if (cinfo->out_color_components > MAX_Q_COMPS)
+    ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
+  /* Make sure colormap indexes can be represented by JSAMPLEs */
+  if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1))
+    ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
+
+  /* Create the colormap and color index table. */
+  create_colormap(cinfo);
+  create_colorindex(cinfo);
+
+  /* Allocate Floyd-Steinberg workspace now if requested.
+   * We do this now since it is FAR storage and may affect the memory
+   * manager's space calculations.  If the user changes to FS dither
+   * mode in a later pass, we will allocate the space then, and will
+   * possibly overrun the max_memory_to_use setting.
+   */
+  if (cinfo->dither_mode == JDITHER_FS)
+    alloc_fs_workspace(cinfo);
+}
+
+#endif /* QUANT_1PASS_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jquant2.c b/Utilities/ITK/Utilities/itkjpeg/jquant2.c
new file mode 100644
index 0000000000000000000000000000000000000000..9f9f7091906c0f455f9c4bc93897161dd7dcf971
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jquant2.c
@@ -0,0 +1,1312 @@
+/*
+ * jquant2.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains 2-pass color quantization (color mapping) routines.
+ * These routines provide selection of a custom color map for an image,
+ * followed by mapping of the image to that color map, with optional
+ * Floyd-Steinberg dithering.
+ * It is also possible to use just the second pass to map to an arbitrary
+ * externally-given color map.
+ *
+ * Note: ordered dithering is not supported, since there isn't any fast
+ * way to compute intercolor distances; it's unclear that ordered dither's
+ * fundamental assumptions even hold with an irregularly spaced color map.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+
+/*
+ * This module implements the well-known Heckbert paradigm for color
+ * quantization.  Most of the ideas used here can be traced back to
+ * Heckbert's seminal paper
+ *   Heckbert, Paul.  "Color Image Quantization for Frame Buffer Display",
+ *   Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304.
+ *
+ * In the first pass over the image, we accumulate a histogram showing the
+ * usage count of each possible color.  To keep the histogram to a reasonable
+ * size, we reduce the precision of the input; typical practice is to retain
+ * 5 or 6 bits per color, so that 8 or 4 different input values are counted
+ * in the same histogram cell.
+ *
+ * Next, the color-selection step begins with a box representing the whole
+ * color space, and repeatedly splits the "largest" remaining box until we
+ * have as many boxes as desired colors.  Then the mean color in each
+ * remaining box becomes one of the possible output colors.
+ * 
+ * The second pass over the image maps each input pixel to the closest output
+ * color (optionally after applying a Floyd-Steinberg dithering correction).
+ * This mapping is logically trivial, but making it go fast enough requires
+ * considerable care.
+ *
+ * Heckbert-style quantizers vary a good deal in their policies for choosing
+ * the "largest" box and deciding where to cut it.  The particular policies
+ * used here have proved out well in experimental comparisons, but better ones
+ * may yet be found.
+ *
+ * In earlier versions of the IJG code, this module quantized in YCbCr color
+ * space, processing the raw upsampled data without a color conversion step.
+ * This allowed the color conversion math to be done only once per colormap
+ * entry, not once per pixel.  However, that optimization precluded other
+ * useful optimizations (such as merging color conversion with upsampling)
+ * and it also interfered with desired capabilities such as quantizing to an
+ * externally-supplied colormap.  We have therefore abandoned that approach.
+ * The present code works in the post-conversion color space, typically RGB.
+ *
+ * To improve the visual quality of the results, we actually work in scaled
+ * RGB space, giving G distances more weight than R, and R in turn more than
+ * B.  To do everything in integer math, we must use integer scale factors.
+ * The 2/3/1 scale factors used here correspond loosely to the relative
+ * weights of the colors in the NTSC grayscale equation.
+ * If you want to use this code to quantize a non-RGB color space, you'll
+ * probably need to change these scale factors.
+ */
+
+#define R_SCALE 2    /* scale R distances by this much */
+#define G_SCALE 3    /* scale G distances by this much */
+#define B_SCALE 1    /* and B by this much */
+
+/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined
+ * in jmorecfg.h.  As the code stands, it will do the right thing for R,G,B
+ * and B,G,R orders.  If you define some other weird order in jmorecfg.h,
+ * you'll get compile errors until you extend this logic.  In that case
+ * you'll probably want to tweak the histogram sizes too.
+ */
+
+#if RGB_RED == 0
+#define C0_SCALE R_SCALE
+#endif
+#if RGB_BLUE == 0
+#define C0_SCALE B_SCALE
+#endif
+#if RGB_GREEN == 1
+#define C1_SCALE G_SCALE
+#endif
+#if RGB_RED == 2
+#define C2_SCALE R_SCALE
+#endif
+#if RGB_BLUE == 2
+#define C2_SCALE B_SCALE
+#endif
+
+
+/*
+ * First we have the histogram data structure and routines for creating it.
+ *
+ * The number of bits of precision can be adjusted by changing these symbols.
+ * We recommend keeping 6 bits for G and 5 each for R and B.
+ * If you have plenty of memory and cycles, 6 bits all around gives marginally
+ * better results; if you are short of memory, 5 bits all around will save
+ * some space but degrade the results.
+ * To maintain a fully accurate histogram, we'd need to allocate a "long"
+ * (preferably unsigned long) for each cell.  In practice this is overkill;
+ * we can get by with 16 bits per cell.  Few of the cell counts will overflow,
+ * and clamping those that do overflow to the maximum value will give close-
+ * enough results.  This reduces the recommended histogram size from 256Kb
+ * to 128Kb, which is a useful savings on PC-class machines.
+ * (In the second pass the histogram space is re-used for pixel mapping data;
+ * in that capacity, each cell must be able to store zero to the number of
+ * desired colors.  16 bits/cell is plenty for that too.)
+ * Since the JPEG code is intended to run in small memory model on 80x86
+ * machines, we can't just allocate the histogram in one chunk.  Instead
+ * of a true 3-D array, we use a row of pointers to 2-D arrays.  Each
+ * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and
+ * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries.  Note that
+ * on 80x86 machines, the pointer row is in near memory but the actual
+ * arrays are in far memory (same arrangement as we use for image arrays).
+ */
+
+#define MAXNUMCOLORS  (MAXJSAMPLE+1) /* maximum size of colormap */
+
+/* These will do the right thing for either R,G,B or B,G,R color order,
+ * but you may not like the results for other color orders.
+ */
+#define HIST_C0_BITS  5    /* bits of precision in R/B histogram */
+#define HIST_C1_BITS  6    /* bits of precision in G histogram */
+#define HIST_C2_BITS  5    /* bits of precision in B/R histogram */
+
+/* Number of elements along histogram axes. */
+#define HIST_C0_ELEMS  (1<<HIST_C0_BITS)
+#define HIST_C1_ELEMS  (1<<HIST_C1_BITS)
+#define HIST_C2_ELEMS  (1<<HIST_C2_BITS)
+
+/* These are the amounts to shift an input value to get a histogram index. */
+#define C0_SHIFT  (BITS_IN_JSAMPLE-HIST_C0_BITS)
+#define C1_SHIFT  (BITS_IN_JSAMPLE-HIST_C1_BITS)
+#define C2_SHIFT  (BITS_IN_JSAMPLE-HIST_C2_BITS)
+
+
+typedef UINT16 histcell;  /* histogram cell; prefer an unsigned type */
+
+typedef histcell FAR * histptr;  /* for pointers to histogram cells */
+
+typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the array */
+typedef hist1d FAR * hist2d;  /* type for the 2nd-level pointers */
+typedef hist2d * hist3d;  /* type for top-level pointer */
+
+
+/* Declarations for Floyd-Steinberg dithering.
+ *
+ * Errors are accumulated into the array fserrors[], at a resolution of
+ * 1/16th of a pixel count.  The error at a given pixel is propagated
+ * to its not-yet-processed neighbors using the standard F-S fractions,
+ *    ...  (here)  7/16
+ *    3/16  5/16  1/16
+ * We work left-to-right on even rows, right-to-left on odd rows.
+ *
+ * We can get away with a single array (holding one row's worth of errors)
+ * by using it to store the current row's errors at pixel columns not yet
+ * processed, but the next row's errors at columns already processed.  We
+ * need only a few extra variables to hold the errors immediately around the
+ * current column.  (If we are lucky, those variables are in registers, but
+ * even if not, they're probably cheaper to access than array elements are.)
+ *
+ * The fserrors[] array has (#columns + 2) entries; the extra entry at
+ * each end saves us from special-casing the first and last pixels.
+ * Each entry is three values long, one value for each color component.
+ *
+ * Note: on a wide image, we might not have enough room in a PC's near data
+ * segment to hold the error array; so it is allocated with alloc_large.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef INT16 FSERROR;    /* 16 bits should be enough */
+typedef int LOCFSERROR;    /* use 'int' for calculation temps */
+#else
+typedef INT32 FSERROR;    /* may need more than 16 bits */
+typedef INT32 LOCFSERROR;  /* be sure calculation temps are big enough */
+#endif
+
+typedef FSERROR FAR *FSERRPTR;  /* pointer to error array (in FAR storage!) */
+
+
+/* Private subobject */
+
+typedef struct {
+  struct jpeg_color_quantizer pub; /* public fields */
+
+  /* Space for the eventually created colormap is stashed here */
+  JSAMPARRAY sv_colormap;  /* colormap allocated at init time */
+  int desired;      /* desired # of colors = size of colormap */
+
+  /* Variables for accumulating image statistics */
+  hist3d histogram;    /* pointer to the histogram */
+
+  boolean needs_zeroed;    /* TRUE if next pass must zero histogram */
+
+  /* Variables for Floyd-Steinberg dithering */
+  FSERRPTR fserrors;    /* accumulated errors */
+  boolean on_odd_row;    /* flag to remember which row we are on */
+  int * error_limiter;    /* table for clamping the applied error */
+} my_cquantizer;
+
+typedef my_cquantizer * my_cquantize_ptr;
+
+
+/*
+ * Prescan some rows of pixels.
+ * In this module the prescan simply updates the histogram, which has been
+ * initialized to zeroes by start_pass.
+ * An output_buf parameter is required by the method signature, but no data
+ * is actually output (in fact the buffer controller is probably passing a
+ * NULL pointer).
+ */
+
+METHODDEF(void)
+prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+      JSAMPARRAY output_buf, int num_rows)
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  register JSAMPROW ptr;
+  register histptr histp;
+  register hist3d histogram = cquantize->histogram;
+  int row;
+  JDIMENSION col;
+  JDIMENSION width = cinfo->output_width;
+  (void)output_buf;
+
+  for (row = 0; row < num_rows; row++) {
+    ptr = input_buf[row];
+    for (col = width; col > 0; col--) {
+      /* get pixel value and index into the histogram */
+      histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
+       [GETJSAMPLE(ptr[1]) >> C1_SHIFT]
+       [GETJSAMPLE(ptr[2]) >> C2_SHIFT];
+      /* increment, check for overflow and undo increment if so. */
+      if (++(*histp) <= 0)
+  (*histp)--;
+      ptr += 3;
+    }
+  }
+}
+
+
+/*
+ * Next we have the really interesting routines: selection of a colormap
+ * given the completed histogram.
+ * These routines work with a list of "boxes", each representing a rectangular
+ * subset of the input color space (to histogram precision).
+ */
+
+typedef struct {
+  /* The bounds of the box (inclusive); expressed as histogram indexes */
+  int c0min, c0max;
+  int c1min, c1max;
+  int c2min, c2max;
+  /* The volume (actually 2-norm) of the box */
+  INT32 volume;
+  /* The number of nonzero histogram cells within this box */
+  long colorcount;
+} box;
+
+typedef box * boxptr;
+
+
+LOCAL(boxptr)
+find_biggest_color_pop (boxptr boxlist, int numboxes)
+/* Find the splittable box with the largest color population */
+/* Returns NULL if no splittable boxes remain */
+{
+  register boxptr boxp;
+  register int i;
+  register long maxc = 0;
+  boxptr which = NULL;
+  
+  for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+    if (boxp->colorcount > maxc && boxp->volume > 0) {
+      which = boxp;
+      maxc = boxp->colorcount;
+    }
+  }
+  return which;
+}
+
+
+LOCAL(boxptr)
+find_biggest_volume (boxptr boxlist, int numboxes)
+/* Find the splittable box with the largest (scaled) volume */
+/* Returns NULL if no splittable boxes remain */
+{
+  register boxptr boxp;
+  register int i;
+  register INT32 maxv = 0;
+  boxptr which = NULL;
+  
+  for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+    if (boxp->volume > maxv) {
+      which = boxp;
+      maxv = boxp->volume;
+    }
+  }
+  return which;
+}
+
+
+LOCAL(void)
+update_box (j_decompress_ptr cinfo, boxptr boxp)
+/* Shrink the min/max bounds of a box to enclose only nonzero elements, */
+/* and recompute its volume and population */
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  hist3d histogram = cquantize->histogram;
+  histptr histp;
+  int c0,c1,c2;
+  int c0min,c0max,c1min,c1max,c2min,c2max;
+  INT32 dist0,dist1,dist2;
+  long ccount;
+  
+  c0min = boxp->c0min;  c0max = boxp->c0max;
+  c1min = boxp->c1min;  c1max = boxp->c1max;
+  c2min = boxp->c2min;  c2max = boxp->c2max;
+  
+  if (c0max > c0min)
+    for (c0 = c0min; c0 <= c0max; c0++)
+      for (c1 = c1min; c1 <= c1max; c1++) {
+  histp = & histogram[c0][c1][c2min];
+  for (c2 = c2min; c2 <= c2max; c2++)
+    if (*histp++ != 0) {
+      boxp->c0min = c0min = c0;
+      goto have_c0min;
+    }
+      }
+ have_c0min:
+  if (c0max > c0min)
+    for (c0 = c0max; c0 >= c0min; c0--)
+      for (c1 = c1min; c1 <= c1max; c1++) {
+  histp = & histogram[c0][c1][c2min];
+  for (c2 = c2min; c2 <= c2max; c2++)
+    if (*histp++ != 0) {
+      boxp->c0max = c0max = c0;
+      goto have_c0max;
+    }
+      }
+ have_c0max:
+  if (c1max > c1min)
+    for (c1 = c1min; c1 <= c1max; c1++)
+      for (c0 = c0min; c0 <= c0max; c0++) {
+  histp = & histogram[c0][c1][c2min];
+  for (c2 = c2min; c2 <= c2max; c2++)
+    if (*histp++ != 0) {
+      boxp->c1min = c1min = c1;
+      goto have_c1min;
+    }
+      }
+ have_c1min:
+  if (c1max > c1min)
+    for (c1 = c1max; c1 >= c1min; c1--)
+      for (c0 = c0min; c0 <= c0max; c0++) {
+  histp = & histogram[c0][c1][c2min];
+  for (c2 = c2min; c2 <= c2max; c2++)
+    if (*histp++ != 0) {
+      boxp->c1max = c1max = c1;
+      goto have_c1max;
+    }
+      }
+ have_c1max:
+  if (c2max > c2min)
+    for (c2 = c2min; c2 <= c2max; c2++)
+      for (c0 = c0min; c0 <= c0max; c0++) {
+  histp = & histogram[c0][c1min][c2];
+  for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
+    if (*histp != 0) {
+      boxp->c2min = c2min = c2;
+      goto have_c2min;
+    }
+      }
+ have_c2min:
+  if (c2max > c2min)
+    for (c2 = c2max; c2 >= c2min; c2--)
+      for (c0 = c0min; c0 <= c0max; c0++) {
+  histp = & histogram[c0][c1min][c2];
+  for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
+    if (*histp != 0) {
+      boxp->c2max = c2max = c2;
+      goto have_c2max;
+    }
+      }
+ have_c2max:
+
+  /* Update box volume.
+   * We use 2-norm rather than real volume here; this biases the method
+   * against making long narrow boxes, and it has the side benefit that
+   * a box is splittable iff norm > 0.
+   * Since the differences are expressed in histogram-cell units,
+   * we have to shift back to JSAMPLE units to get consistent distances;
+   * after which, we scale according to the selected distance scale factors.
+   */
+  dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
+  dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
+  dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
+  boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
+  
+  /* Now scan remaining volume of box and compute population */
+  ccount = 0;
+  for (c0 = c0min; c0 <= c0max; c0++)
+    for (c1 = c1min; c1 <= c1max; c1++) {
+      histp = & histogram[c0][c1][c2min];
+      for (c2 = c2min; c2 <= c2max; c2++, histp++)
+  if (*histp != 0) {
+    ccount++;
+  }
+    }
+  boxp->colorcount = ccount;
+}
+
+
+LOCAL(int)
+median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
+      int desired_colors)
+/* Repeatedly select and split the largest box until we have enough boxes */
+{
+  int n,lb;
+  int c0,c1,c2,cmax;
+  register boxptr b1,b2;
+
+  while (numboxes < desired_colors) {
+    /* Select box to split.
+     * Current algorithm: by population for first half, then by volume.
+     */
+    if (numboxes*2 <= desired_colors) {
+      b1 = find_biggest_color_pop(boxlist, numboxes);
+    } else {
+      b1 = find_biggest_volume(boxlist, numboxes);
+    }
+    if (b1 == NULL)    /* no splittable boxes left! */
+      break;
+    b2 = &boxlist[numboxes];  /* where new box will go */
+    /* Copy the color bounds to the new box. */
+    b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
+    b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
+    /* Choose which axis to split the box on.
+     * Current algorithm: longest scaled axis.
+     * See notes in update_box about scaling distances.
+     */
+    c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE;
+    c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE;
+    c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE;
+    /* We want to break any ties in favor of green, then red, blue last.
+     * This code does the right thing for R,G,B or B,G,R color orders only.
+     */
+#if RGB_RED == 0
+    cmax = c1; n = 1;
+    if (c0 > cmax) { cmax = c0; n = 0; }
+    if (c2 > cmax) { n = 2; }
+#else
+    cmax = c1; n = 1;
+    if (c2 > cmax) { cmax = c2; n = 2; }
+    if (c0 > cmax) { n = 0; }
+#endif
+    /* Choose split point along selected axis, and update box bounds.
+     * Current algorithm: split at halfway point.
+     * (Since the box has been shrunk to minimum volume,
+     * any split will produce two nonempty subboxes.)
+     * Note that lb value is max for lower box, so must be < old max.
+     */
+    switch (n) {
+    case 0:
+      lb = (b1->c0max + b1->c0min) / 2;
+      b1->c0max = lb;
+      b2->c0min = lb+1;
+      break;
+    case 1:
+      lb = (b1->c1max + b1->c1min) / 2;
+      b1->c1max = lb;
+      b2->c1min = lb+1;
+      break;
+    case 2:
+      lb = (b1->c2max + b1->c2min) / 2;
+      b1->c2max = lb;
+      b2->c2min = lb+1;
+      break;
+    }
+    /* Update stats for boxes */
+    update_box(cinfo, b1);
+    update_box(cinfo, b2);
+    numboxes++;
+  }
+  return numboxes;
+}
+
+
+LOCAL(void)
+compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
+/* Compute representative color for a box, put it in colormap[icolor] */
+{
+  /* Current algorithm: mean weighted by pixels (not colors) */
+  /* Note it is important to get the rounding correct! */
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  hist3d histogram = cquantize->histogram;
+  histptr histp;
+  int c0,c1,c2;
+  int c0min,c0max,c1min,c1max,c2min,c2max;
+  long count;
+  long total = 0;
+  long c0total = 0;
+  long c1total = 0;
+  long c2total = 0;
+  
+  c0min = boxp->c0min;  c0max = boxp->c0max;
+  c1min = boxp->c1min;  c1max = boxp->c1max;
+  c2min = boxp->c2min;  c2max = boxp->c2max;
+  
+  for (c0 = c0min; c0 <= c0max; c0++)
+    for (c1 = c1min; c1 <= c1max; c1++) {
+      histp = & histogram[c0][c1][c2min];
+      for (c2 = c2min; c2 <= c2max; c2++) {
+  if ((count = *histp++) != 0) {
+    total += count;
+    c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count;
+    c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count;
+    c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count;
+  }
+      }
+    }
+  
+  cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
+  cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
+  cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
+}
+
+
+LOCAL(void)
+select_colors (j_decompress_ptr cinfo, int desired_colors)
+/* Master routine for color selection */
+{
+  boxptr boxlist;
+  int numboxes;
+  int i;
+
+  /* Allocate workspace for box list */
+  boxlist = (boxptr) (*cinfo->mem->alloc_small)
+    ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box));
+  /* Initialize one box containing whole space */
+  numboxes = 1;
+  boxlist[0].c0min = 0;
+  boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT;
+  boxlist[0].c1min = 0;
+  boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT;
+  boxlist[0].c2min = 0;
+  boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT;
+  /* Shrink it to actually-used volume and set its statistics */
+  update_box(cinfo, & boxlist[0]);
+  /* Perform median-cut to produce final box list */
+  numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
+  /* Compute the representative color for each box, fill colormap */
+  for (i = 0; i < numboxes; i++)
+    compute_color(cinfo, & boxlist[i], i);
+  cinfo->actual_number_of_colors = numboxes;
+  TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes);
+}
+
+
+/*
+ * These routines are concerned with the time-critical task of mapping input
+ * colors to the nearest color in the selected colormap.
+ *
+ * We re-use the histogram space as an "inverse color map", essentially a
+ * cache for the results of nearest-color searches.  All colors within a
+ * histogram cell will be mapped to the same colormap entry, namely the one
+ * closest to the cell's center.  This may not be quite the closest entry to
+ * the actual input color, but it's almost as good.  A zero in the cache
+ * indicates we haven't found the nearest color for that cell yet; the array
+ * is cleared to zeroes before starting the mapping pass.  When we find the
+ * nearest color for a cell, its colormap index plus one is recorded in the
+ * cache for future use.  The pass2 scanning routines call fill_inverse_cmap
+ * when they need to use an unfilled entry in the cache.
+ *
+ * Our method of efficiently finding nearest colors is based on the "locally
+ * sorted search" idea described by Heckbert and on the incremental distance
+ * calculation described by Spencer W. Thomas in chapter III.1 of Graphics
+ * Gems II (James Arvo, ed.  Academic Press, 1991).  Thomas points out that
+ * the distances from a given colormap entry to each cell of the histogram can
+ * be computed quickly using an incremental method: the differences between
+ * distances to adjacent cells themselves differ by a constant.  This allows a
+ * fairly fast implementation of the "brute force" approach of computing the
+ * distance from every colormap entry to every histogram cell.  Unfortunately,
+ * it needs a work array to hold the best-distance-so-far for each histogram
+ * cell (because the inner loop has to be over cells, not colormap entries).
+ * The work array elements have to be INT32s, so the work array would need
+ * 256Kb at our recommended precision.  This is not feasible in DOS machines.
+ *
+ * To get around these problems, we apply Thomas' method to compute the
+ * nearest colors for only the cells within a small subbox of the histogram.
+ * The work array need be only as big as the subbox, so the memory usage
+ * problem is solved.  Furthermore, we need not fill subboxes that are never
+ * referenced in pass2; many images use only part of the color gamut, so a
+ * fair amount of work is saved.  An additional advantage of this
+ * approach is that we can apply Heckbert's locality criterion to quickly
+ * eliminate colormap entries that are far away from the subbox; typically
+ * three-fourths of the colormap entries are rejected by Heckbert's criterion,
+ * and we need not compute their distances to individual cells in the subbox.
+ * The speed of this approach is heavily influenced by the subbox size: too
+ * small means too much overhead, too big loses because Heckbert's criterion
+ * can't eliminate as many colormap entries.  Empirically the best subbox
+ * size seems to be about 1/512th of the histogram (1/8th in each direction).
+ *
+ * Thomas' article also describes a refined method which is asymptotically
+ * faster than the brute-force method, but it is also far more complex and
+ * cannot efficiently be applied to small subboxes.  It is therefore not
+ * useful for programs intended to be portable to DOS machines.  On machines
+ * with plenty of memory, filling the whole histogram in one shot with Thomas'
+ * refined method might be faster than the present code --- but then again,
+ * it might not be any faster, and it's certainly more complicated.
+ */
+
+
+/* log2(histogram cells in update box) for each axis; this can be adjusted */
+#define BOX_C0_LOG  (HIST_C0_BITS-3)
+#define BOX_C1_LOG  (HIST_C1_BITS-3)
+#define BOX_C2_LOG  (HIST_C2_BITS-3)
+
+#define BOX_C0_ELEMS  (1<<BOX_C0_LOG) /* # of hist cells in update box */
+#define BOX_C1_ELEMS  (1<<BOX_C1_LOG)
+#define BOX_C2_ELEMS  (1<<BOX_C2_LOG)
+
+#define BOX_C0_SHIFT  (C0_SHIFT + BOX_C0_LOG)
+#define BOX_C1_SHIFT  (C1_SHIFT + BOX_C1_LOG)
+#define BOX_C2_SHIFT  (C2_SHIFT + BOX_C2_LOG)
+
+
+/*
+ * The next three routines implement inverse colormap filling.  They could
+ * all be folded into one big routine, but splitting them up this way saves
+ * some stack space (the mindist[] and bestdist[] arrays need not coexist)
+ * and may allow some compilers to produce better code by registerizing more
+ * inner-loop variables.
+ */
+
+LOCAL(int)
+find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+        JSAMPLE colorlist[])
+/* Locate the colormap entries close enough to an update box to be candidates
+ * for the nearest entry to some cell(s) in the update box.  The update box
+ * is specified by the center coordinates of its first cell.  The number of
+ * candidate colormap entries is returned, and their colormap indexes are
+ * placed in colorlist[].
+ * This routine uses Heckbert's "locally sorted search" criterion to select
+ * the colors that need further consideration.
+ */
+{
+  int numcolors = cinfo->actual_number_of_colors;
+  int maxc0, maxc1, maxc2;
+  int centerc0, centerc1, centerc2;
+  int i, x, ncolors;
+  INT32 minmaxdist, min_dist, max_dist, tdist;
+  INT32 mindist[MAXNUMCOLORS];  /* min distance to colormap entry i */
+
+  /* Compute true coordinates of update box's upper corner and center.
+   * Actually we compute the coordinates of the center of the upper-corner
+   * histogram cell, which are the upper bounds of the volume we care about.
+   * Note that since ">>" rounds down, the "center" values may be closer to
+   * min than to max; hence comparisons to them must be "<=", not "<".
+   */
+  maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));
+  centerc0 = (minc0 + maxc0) >> 1;
+  maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));
+  centerc1 = (minc1 + maxc1) >> 1;
+  maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));
+  centerc2 = (minc2 + maxc2) >> 1;
+
+  /* For each color in colormap, find:
+   *  1. its minimum squared-distance to any point in the update box
+   *     (zero if color is within update box);
+   *  2. its maximum squared-distance to any point in the update box.
+   * Both of these can be found by considering only the corners of the box.
+   * We save the minimum distance for each color in mindist[];
+   * only the smallest maximum distance is of interest.
+   */
+  minmaxdist = 0x7FFFFFFFL;
+
+  for (i = 0; i < numcolors; i++) {
+    /* We compute the squared-c0-distance term, then add in the other two. */
+    x = GETJSAMPLE(cinfo->colormap[0][i]);
+    if (x < minc0) {
+      tdist = (x - minc0) * C0_SCALE;
+      min_dist = tdist*tdist;
+      tdist = (x - maxc0) * C0_SCALE;
+      max_dist = tdist*tdist;
+    } else if (x > maxc0) {
+      tdist = (x - maxc0) * C0_SCALE;
+      min_dist = tdist*tdist;
+      tdist = (x - minc0) * C0_SCALE;
+      max_dist = tdist*tdist;
+    } else {
+      /* within cell range so no contribution to min_dist */
+      min_dist = 0;
+      if (x <= centerc0) {
+  tdist = (x - maxc0) * C0_SCALE;
+  max_dist = tdist*tdist;
+      } else {
+  tdist = (x - minc0) * C0_SCALE;
+  max_dist = tdist*tdist;
+      }
+    }
+
+    x = GETJSAMPLE(cinfo->colormap[1][i]);
+    if (x < minc1) {
+      tdist = (x - minc1) * C1_SCALE;
+      min_dist += tdist*tdist;
+      tdist = (x - maxc1) * C1_SCALE;
+      max_dist += tdist*tdist;
+    } else if (x > maxc1) {
+      tdist = (x - maxc1) * C1_SCALE;
+      min_dist += tdist*tdist;
+      tdist = (x - minc1) * C1_SCALE;
+      max_dist += tdist*tdist;
+    } else {
+      /* within cell range so no contribution to min_dist */
+      if (x <= centerc1) {
+  tdist = (x - maxc1) * C1_SCALE;
+  max_dist += tdist*tdist;
+      } else {
+  tdist = (x - minc1) * C1_SCALE;
+  max_dist += tdist*tdist;
+      }
+    }
+
+    x = GETJSAMPLE(cinfo->colormap[2][i]);
+    if (x < minc2) {
+      tdist = (x - minc2) * C2_SCALE;
+      min_dist += tdist*tdist;
+      tdist = (x - maxc2) * C2_SCALE;
+      max_dist += tdist*tdist;
+    } else if (x > maxc2) {
+      tdist = (x - maxc2) * C2_SCALE;
+      min_dist += tdist*tdist;
+      tdist = (x - minc2) * C2_SCALE;
+      max_dist += tdist*tdist;
+    } else {
+      /* within cell range so no contribution to min_dist */
+      if (x <= centerc2) {
+  tdist = (x - maxc2) * C2_SCALE;
+  max_dist += tdist*tdist;
+      } else {
+  tdist = (x - minc2) * C2_SCALE;
+  max_dist += tdist*tdist;
+      }
+    }
+
+    mindist[i] = min_dist;  /* save away the results */
+    if (max_dist < minmaxdist)
+      minmaxdist = max_dist;
+  }
+
+  /* Now we know that no cell in the update box is more than minmaxdist
+   * away from some colormap entry.  Therefore, only colors that are
+   * within minmaxdist of some part of the box need be considered.
+   */
+  ncolors = 0;
+  for (i = 0; i < numcolors; i++) {
+    if (mindist[i] <= minmaxdist)
+      colorlist[ncolors++] = (JSAMPLE) i;
+  }
+  return ncolors;
+}
+
+
+LOCAL(void)
+find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+      int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
+/* Find the closest colormap entry for each cell in the update box,
+ * given the list of candidate colors prepared by find_nearby_colors.
+ * Return the indexes of the closest entries in the bestcolor[] array.
+ * This routine uses Thomas' incremental distance calculation method to
+ * find the distance from a colormap entry to successive cells in the box.
+ */
+{
+  int ic0, ic1, ic2;
+  int i, icolor;
+  register INT32 * bptr;  /* pointer into bestdist[] array */
+  JSAMPLE * cptr;    /* pointer into bestcolor[] array */
+  INT32 dist0, dist1;    /* initial distance values */
+  register INT32 dist2;    /* current distance in inner loop */
+  INT32 xx0, xx1;    /* distance increments */
+  register INT32 xx2;
+  INT32 inc0, inc1, inc2;  /* initial values for increments */
+  /* This array holds the distance to the nearest-so-far color for each cell */
+  INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
+
+  /* Initialize best-distance for each cell of the update box */
+  bptr = bestdist;
+  for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
+    *bptr++ = 0x7FFFFFFFL;
+  
+  /* For each color selected by find_nearby_colors,
+   * compute its distance to the center of each cell in the box.
+   * If that's less than best-so-far, update best distance and color number.
+   */
+  
+  /* Nominal steps between cell centers ("x" in Thomas article) */
+#define STEP_C0  ((1 << C0_SHIFT) * C0_SCALE)
+#define STEP_C1  ((1 << C1_SHIFT) * C1_SCALE)
+#define STEP_C2  ((1 << C2_SHIFT) * C2_SCALE)
+  
+  for (i = 0; i < numcolors; i++) {
+    icolor = GETJSAMPLE(colorlist[i]);
+    /* Compute (square of) distance from minc0/c1/c2 to this color */
+    inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
+    dist0 = inc0*inc0;
+    inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
+    dist0 += inc1*inc1;
+    inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
+    dist0 += inc2*inc2;
+    /* Form the initial difference increments */
+    inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
+    inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
+    inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;
+    /* Now loop over all cells in box, updating distance per Thomas method */
+    bptr = bestdist;
+    cptr = bestcolor;
+    xx0 = inc0;
+    for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) {
+      dist1 = dist0;
+      xx1 = inc1;
+      for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) {
+  dist2 = dist1;
+  xx2 = inc2;
+  for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) {
+    if (dist2 < *bptr) {
+      *bptr = dist2;
+      *cptr = (JSAMPLE) icolor;
+    }
+    dist2 += xx2;
+    xx2 += 2 * STEP_C2 * STEP_C2;
+    bptr++;
+    cptr++;
+  }
+  dist1 += xx1;
+  xx1 += 2 * STEP_C1 * STEP_C1;
+      }
+      dist0 += xx0;
+      xx0 += 2 * STEP_C0 * STEP_C0;
+    }
+  }
+}
+
+
+LOCAL(void)
+fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
+/* Fill the inverse-colormap entries in the update box that contains */
+/* histogram cell c0/c1/c2.  (Only that one cell MUST be filled, but */
+/* we can fill as many others as we wish.) */
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  hist3d histogram = cquantize->histogram;
+  int minc0, minc1, minc2;  /* lower left corner of update box */
+  int ic0, ic1, ic2;
+  register JSAMPLE * cptr;  /* pointer into bestcolor[] array */
+  register histptr cachep;  /* pointer into main cache array */
+  /* This array lists the candidate colormap indexes. */
+  JSAMPLE colorlist[MAXNUMCOLORS];
+  int numcolors;    /* number of candidate colors */
+  /* This array holds the actually closest colormap index for each cell. */
+  JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
+
+  /* Convert cell coordinates to update box ID */
+  c0 >>= BOX_C0_LOG;
+  c1 >>= BOX_C1_LOG;
+  c2 >>= BOX_C2_LOG;
+
+  /* Compute true coordinates of update box's origin corner.
+   * Actually we compute the coordinates of the center of the corner
+   * histogram cell, which are the lower bounds of the volume we care about.
+   */
+  minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
+  minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
+  minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
+  
+  /* Determine which colormap entries are close enough to be candidates
+   * for the nearest entry to some cell in the update box.
+   */
+  numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist);
+
+  /* Determine the actually nearest colors. */
+  find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist,
+       bestcolor);
+
+  /* Save the best color numbers (plus 1) in the main cache array */
+  c0 <<= BOX_C0_LOG;    /* convert ID back to base cell indexes */
+  c1 <<= BOX_C1_LOG;
+  c2 <<= BOX_C2_LOG;
+  cptr = bestcolor;
+  for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
+    for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
+      cachep = & histogram[c0+ic0][c1+ic1][c2];
+      for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
+  *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1);
+      }
+    }
+  }
+}
+
+
+/*
+ * Map some rows of pixels to the output colormapped representation.
+ */
+
+METHODDEF(void)
+pass2_no_dither (j_decompress_ptr cinfo,
+     JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+/* This version performs no dithering */
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  hist3d histogram = cquantize->histogram;
+  register JSAMPROW inptr, outptr;
+  register histptr cachep;
+  register int c0, c1, c2;
+  int row;
+  JDIMENSION col;
+  JDIMENSION width = cinfo->output_width;
+
+  for (row = 0; row < num_rows; row++) {
+    inptr = input_buf[row];
+    outptr = output_buf[row];
+    for (col = width; col > 0; col--) {
+      /* get pixel value and index into the cache */
+      c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
+      c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
+      c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
+      cachep = & histogram[c0][c1][c2];
+      /* If we have not seen this color before, find nearest colormap entry */
+      /* and update the cache */
+      if (*cachep == 0)
+  fill_inverse_cmap(cinfo, c0,c1,c2);
+      /* Now emit the colormap index for this cell */
+      *outptr++ = (JSAMPLE) (*cachep - 1);
+    }
+  }
+}
+
+
+METHODDEF(void)
+pass2_fs_dither (j_decompress_ptr cinfo,
+     JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+/* This version performs Floyd-Steinberg dithering */
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  hist3d histogram = cquantize->histogram;
+  register LOCFSERROR cur0, cur1, cur2;  /* current error or pixel value */
+  LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */
+  LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */
+  register FSERRPTR errorptr;  /* => fserrors[] at column before current */
+  JSAMPROW inptr;    /* => current input pixel */
+  JSAMPROW outptr;    /* => current output pixel */
+  histptr cachep;
+  int dir;      /* +1 or -1 depending on direction */
+  int dir3;      /* 3*dir, for advancing inptr & errorptr */
+  int row;
+  JDIMENSION col;
+  JDIMENSION width = cinfo->output_width;
+  JSAMPLE *range_limit = cinfo->sample_range_limit;
+  int *error_limit = cquantize->error_limiter;
+  JSAMPROW colormap0 = cinfo->colormap[0];
+  JSAMPROW colormap1 = cinfo->colormap[1];
+  JSAMPROW colormap2 = cinfo->colormap[2];
+  SHIFT_TEMPS
+
+  for (row = 0; row < num_rows; row++) {
+    inptr = input_buf[row];
+    outptr = output_buf[row];
+    if (cquantize->on_odd_row) {
+      /* work right to left in this row */
+      inptr += (width-1) * 3;  /* so point to rightmost pixel */
+      outptr += width-1;
+      dir = -1;
+      dir3 = -3;
+      errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */
+      cquantize->on_odd_row = FALSE; /* flip for next time */
+    } else {
+      /* work left to right in this row */
+      dir = 1;
+      dir3 = 3;
+      errorptr = cquantize->fserrors; /* => entry before first real column */
+      cquantize->on_odd_row = TRUE; /* flip for next time */
+    }
+    /* Preset error values: no error propagated to first pixel from left */
+    cur0 = cur1 = cur2 = 0;
+    /* and no error propagated to row below yet */
+    belowerr0 = belowerr1 = belowerr2 = 0;
+    bpreverr0 = bpreverr1 = bpreverr2 = 0;
+
+    for (col = width; col > 0; col--) {
+      /* curN holds the error propagated from the previous pixel on the
+       * current line.  Add the error propagated from the previous line
+       * to form the complete error correction term for this pixel, and
+       * round the error term (which is expressed * 16) to an integer.
+       * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
+       * for either sign of the error value.
+       * Note: errorptr points to *previous* column's array entry.
+       */
+      cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4);
+      cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4);
+      cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4);
+      /* Limit the error using transfer function set by init_error_limit.
+       * See comments with init_error_limit for rationale.
+       */
+      cur0 = error_limit[cur0];
+      cur1 = error_limit[cur1];
+      cur2 = error_limit[cur2];
+      /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
+       * The maximum error is +- MAXJSAMPLE (or less with error limiting);
+       * this sets the required size of the range_limit array.
+       */
+      cur0 += GETJSAMPLE(inptr[0]);
+      cur1 += GETJSAMPLE(inptr[1]);
+      cur2 += GETJSAMPLE(inptr[2]);
+      cur0 = GETJSAMPLE(range_limit[cur0]);
+      cur1 = GETJSAMPLE(range_limit[cur1]);
+      cur2 = GETJSAMPLE(range_limit[cur2]);
+      /* Index into the cache with adjusted pixel value */
+      cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT];
+      /* If we have not seen this color before, find nearest colormap */
+      /* entry and update the cache */
+      if (*cachep == 0)
+  fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT);
+      /* Now emit the colormap index for this cell */
+      { register int pixcode = *cachep - 1;
+  *outptr = (JSAMPLE) pixcode;
+  /* Compute representation error for this pixel */
+  cur0 -= GETJSAMPLE(colormap0[pixcode]);
+  cur1 -= GETJSAMPLE(colormap1[pixcode]);
+  cur2 -= GETJSAMPLE(colormap2[pixcode]);
+      }
+      /* Compute error fractions to be propagated to adjacent pixels.
+       * Add these into the running sums, and simultaneously shift the
+       * next-line error sums left by 1 column.
+       */
+      { register LOCFSERROR bnexterr, delta;
+
+  bnexterr = cur0;  /* Process component 0 */
+  delta = cur0 * 2;
+  cur0 += delta;    /* form error * 3 */
+  errorptr[0] = (FSERROR) (bpreverr0 + cur0);
+  cur0 += delta;    /* form error * 5 */
+  bpreverr0 = belowerr0 + cur0;
+  belowerr0 = bnexterr;
+  cur0 += delta;    /* form error * 7 */
+  bnexterr = cur1;  /* Process component 1 */
+  delta = cur1 * 2;
+  cur1 += delta;    /* form error * 3 */
+  errorptr[1] = (FSERROR) (bpreverr1 + cur1);
+  cur1 += delta;    /* form error * 5 */
+  bpreverr1 = belowerr1 + cur1;
+  belowerr1 = bnexterr;
+  cur1 += delta;    /* form error * 7 */
+  bnexterr = cur2;  /* Process component 2 */
+  delta = cur2 * 2;
+  cur2 += delta;    /* form error * 3 */
+  errorptr[2] = (FSERROR) (bpreverr2 + cur2);
+  cur2 += delta;    /* form error * 5 */
+  bpreverr2 = belowerr2 + cur2;
+  belowerr2 = bnexterr;
+  cur2 += delta;    /* form error * 7 */
+      }
+      /* At this point curN contains the 7/16 error value to be propagated
+       * to the next pixel on the current line, and all the errors for the
+       * next line have been shifted over.  We are therefore ready to move on.
+       */
+      inptr += dir3;    /* Advance pixel pointers to next column */
+      outptr += dir;
+      errorptr += dir3;    /* advance errorptr to current column */
+    }
+    /* Post-loop cleanup: we must unload the final error values into the
+     * final fserrors[] entry.  Note we need not unload belowerrN because
+     * it is for the dummy column before or after the actual array.
+     */
+    errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */
+    errorptr[1] = (FSERROR) bpreverr1;
+    errorptr[2] = (FSERROR) bpreverr2;
+  }
+}
+
+
+/*
+ * Initialize the error-limiting transfer function (lookup table).
+ * The raw F-S error computation can potentially compute error values of up to
+ * +- MAXJSAMPLE.  But we want the maximum correction applied to a pixel to be
+ * much less, otherwise obviously wrong pixels will be created.  (Typical
+ * effects include weird fringes at color-area boundaries, isolated bright
+ * pixels in a dark area, etc.)  The standard advice for avoiding this problem
+ * is to ensure that the "corners" of the color cube are allocated as output
+ * colors; then repeated errors in the same direction cannot cause cascading
+ * error buildup.  However, that only prevents the error from getting
+ * completely out of hand; Aaron Giles reports that error limiting improves
+ * the results even with corner colors allocated.
+ * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty
+ * well, but the smoother transfer function used below is even better.  Thanks
+ * to Aaron Giles for this idea.
+ */
+
+LOCAL(void)
+init_error_limit (j_decompress_ptr cinfo)
+/* Allocate and fill in the error_limiter table */
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  int * table;
+  int in, out;
+
+  table = (int *) (*cinfo->mem->alloc_small)
+    ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int));
+  table += MAXJSAMPLE;    /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */
+  cquantize->error_limiter = table;
+
+#define STEPSIZE ((MAXJSAMPLE+1)/16)
+  /* Map errors 1:1 up to +- MAXJSAMPLE/16 */
+  out = 0;
+  for (in = 0; in < STEPSIZE; in++, out++) {
+    table[in] = out; table[-in] = -out;
+  }
+  /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */
+  for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) {
+    table[in] = out; table[-in] = -out;
+  }
+  /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */
+  for (; in <= MAXJSAMPLE; in++) {
+    table[in] = out; table[-in] = -out;
+  }
+#undef STEPSIZE
+}
+
+
+/*
+ * Finish up at the end of each pass.
+ */
+
+METHODDEF(void)
+finish_pass1 (j_decompress_ptr cinfo)
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
+  /* Select the representative colors and fill in cinfo->colormap */
+  cinfo->colormap = cquantize->sv_colormap;
+  select_colors(cinfo, cquantize->desired);
+  /* Force next pass to zero the color index table */
+  cquantize->needs_zeroed = TRUE;
+}
+
+
+METHODDEF(void)
+finish_pass2 (j_decompress_ptr cinfo)
+{
+  (void)cinfo;
+  /* no work */
+}
+
+
+/*
+ * Initialize for each processing pass.
+ */
+
+METHODDEF(void)
+start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+  hist3d histogram = cquantize->histogram;
+  int i;
+
+  /* Only F-S dithering or no dithering is supported. */
+  /* If user asks for ordered dither, give him F-S. */
+  if (cinfo->dither_mode != JDITHER_NONE)
+    cinfo->dither_mode = JDITHER_FS;
+
+  if (is_pre_scan) {
+    /* Set up method pointers */
+    cquantize->pub.color_quantize = prescan_quantize;
+    cquantize->pub.finish_pass = finish_pass1;
+    cquantize->needs_zeroed = TRUE; /* Always zero histogram */
+  } else {
+    /* Set up method pointers */
+    if (cinfo->dither_mode == JDITHER_FS)
+      cquantize->pub.color_quantize = pass2_fs_dither;
+    else
+      cquantize->pub.color_quantize = pass2_no_dither;
+    cquantize->pub.finish_pass = finish_pass2;
+
+    /* Make sure color count is acceptable */
+    i = cinfo->actual_number_of_colors;
+    if (i < 1)
+      ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1);
+    if (i > MAXNUMCOLORS)
+      ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+
+    if (cinfo->dither_mode == JDITHER_FS) {
+      size_t arraysize = (size_t) ((cinfo->output_width + 2) *
+           (3 * SIZEOF(FSERROR)));
+      /* Allocate Floyd-Steinberg workspace if we didn't already. */
+      if (cquantize->fserrors == NULL)
+  cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
+    ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+      /* Initialize the propagated errors to zero. */
+      jzero_far((void FAR *) cquantize->fserrors, arraysize);
+      /* Make the error-limit table if we didn't already. */
+      if (cquantize->error_limiter == NULL)
+  init_error_limit(cinfo);
+      cquantize->on_odd_row = FALSE;
+    }
+
+  }
+  /* Zero the histogram or inverse color map, if necessary */
+  if (cquantize->needs_zeroed) {
+    for (i = 0; i < HIST_C0_ELEMS; i++) {
+      jzero_far((void FAR *) histogram[i],
+    HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+    }
+    cquantize->needs_zeroed = FALSE;
+  }
+}
+
+
+/*
+ * Switch to a new external colormap between output passes.
+ */
+
+METHODDEF(void)
+new_color_map_2_quant (j_decompress_ptr cinfo)
+{
+  my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
+  /* Reset the inverse color map */
+  cquantize->needs_zeroed = TRUE;
+}
+
+
+/*
+ * Module initialization routine for 2-pass color quantization.
+ */
+
+GLOBAL(void)
+jinit_2pass_quantizer (j_decompress_ptr cinfo)
+{
+  my_cquantize_ptr cquantize;
+  int i;
+
+  cquantize = (my_cquantize_ptr)
+    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+        SIZEOF(my_cquantizer));
+  cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+  cquantize->pub.start_pass = start_pass_2_quant;
+  cquantize->pub.new_color_map = new_color_map_2_quant;
+  cquantize->fserrors = NULL;  /* flag optional arrays not allocated */
+  cquantize->error_limiter = NULL;
+
+  /* Make sure jdmaster didn't give me a case I can't handle */
+  if (cinfo->out_color_components != 3)
+    ERREXIT(cinfo, JERR_NOTIMPL);
+
+  /* Allocate the histogram/inverse colormap storage */
+  cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small)
+    ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d));
+  for (i = 0; i < HIST_C0_ELEMS; i++) {
+    cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large)
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+  }
+  cquantize->needs_zeroed = TRUE; /* histogram is garbage now */
+
+  /* Allocate storage for the completed colormap, if required.
+   * We do this now since it is FAR storage and may affect
+   * the memory manager's space calculations.
+   */
+  if (cinfo->enable_2pass_quant) {
+    /* Make sure color count is acceptable */
+    int desired = cinfo->desired_number_of_colors;
+    /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
+    if (desired < 8)
+      ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
+    /* Make sure colormap indexes can be represented by JSAMPLEs */
+    if (desired > MAXNUMCOLORS)
+      ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+    cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
+      ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3);
+    cquantize->desired = desired;
+  } else
+    cquantize->sv_colormap = NULL;
+
+  /* Only F-S dithering or no dithering is supported. */
+  /* If user asks for ordered dither, give him F-S. */
+  if (cinfo->dither_mode != JDITHER_NONE)
+    cinfo->dither_mode = JDITHER_FS;
+
+  /* Allocate Floyd-Steinberg workspace if necessary.
+   * This isn't really needed until pass 2, but again it is FAR storage.
+   * Although we will cope with a later change in dither_mode,
+   * we do not promise to honor max_memory_to_use if dither_mode changes.
+   */
+  if (cinfo->dither_mode == JDITHER_FS) {
+    cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
+      ((j_common_ptr) cinfo, JPOOL_IMAGE,
+       (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))));
+    /* Might as well create the error-limiting table too. */
+    init_error_limit(cinfo);
+  }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
diff --git a/Utilities/ITK/Utilities/itkjpeg/jutils.c b/Utilities/ITK/Utilities/itkjpeg/jutils.c
new file mode 100644
index 0000000000000000000000000000000000000000..23abeb881f8a1cdc7474d2e53c6add73250ab8d3
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jutils.c
@@ -0,0 +1,179 @@
+/*
+ * jutils.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains tables and miscellaneous utility routines needed
+ * for both compression and decompression.
+ * Note we prefix all global names with "j" to minimize conflicts with
+ * a surrounding application.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element
+ * of a DCT block read in natural order (left to right, top to bottom).
+ */
+
+#if 0        /* This table is not actually needed in v6a */
+
+const int jpeg_zigzag_order[DCTSIZE2] = {
+   0,  1,  5,  6, 14, 15, 27, 28,
+   2,  4,  7, 13, 16, 26, 29, 42,
+   3,  8, 12, 17, 25, 30, 41, 43,
+   9, 11, 18, 24, 31, 40, 44, 53,
+  10, 19, 23, 32, 39, 45, 52, 54,
+  20, 22, 33, 38, 46, 51, 55, 60,
+  21, 34, 37, 47, 50, 56, 59, 61,
+  35, 36, 48, 49, 57, 58, 62, 63
+};
+
+#endif
+
+/*
+ * jpeg_natural_order[i] is the natural-order position of the i'th element
+ * of zigzag order.
+ *
+ * When reading corrupted data, the Huffman decoders could attempt
+ * to reference an entry beyond the end of this array (if the decoded
+ * zero run length reaches past the end of the block).  To prevent
+ * wild stores without adding an inner-loop test, we put some extra
+ * "63"s after the real entries.  This will cause the extra coefficient
+ * to be stored in location 63 of the block, not somewhere random.
+ * The worst case would be a run-length of 15, which means we need 16
+ * fake entries.
+ */
+
+const int jpeg_natural_order[DCTSIZE2+16] = {
+  0,  1,  8, 16,  9,  2,  3, 10,
+ 17, 24, 32, 25, 18, 11,  4,  5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13,  6,  7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */
+ 63, 63, 63, 63, 63, 63, 63, 63
+};
+
+
+/*
+ * Arithmetic utilities
+ */
+
+GLOBAL(long)
+jdiv_round_up (long a, long b)
+/* Compute a/b rounded up to next integer, ie, ceil(a/b) */
+/* Assumes a >= 0, b > 0 */
+{
+  return (a + b - 1L) / b;
+}
+
+
+GLOBAL(long)
+jround_up (long a, long b)
+/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
+/* Assumes a >= 0, b > 0 */
+{
+  a += b - 1L;
+  return a - (a % b);
+}
+
+
+/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays
+ * and coefficient-block arrays.  This won't work on 80x86 because the arrays
+ * are FAR and we're assuming a small-pointer memory model.  However, some
+ * DOS compilers provide far-pointer versions of memcpy() and memset() even
+ * in the small-model libraries.  These will be used if USE_FMEM is defined.
+ * Otherwise, the routines below do it the hard way.  (The performance cost
+ * is not all that great, because these routines aren't very heavily used.)
+ */
+
+#ifndef NEED_FAR_POINTERS  /* normal case, same as regular macros */
+#define FMEMCOPY(dest,src,size)  MEMCOPY(dest,src,size)
+#define FMEMZERO(target,size)  MEMZERO(target,size)
+#else        /* 80x86 case, define if we can */
+#ifdef USE_FMEM
+#define FMEMCOPY(dest,src,size)  _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size))
+#define FMEMZERO(target,size)  _fmemset((void FAR *)(target), 0, (size_t)(size))
+#endif
+#endif
+
+
+GLOBAL(void)
+jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
+       JSAMPARRAY output_array, int dest_row,
+       int num_rows, JDIMENSION num_cols)
+/* Copy some rows of samples from one place to another.
+ * num_rows rows are copied from input_array[source_row++]
+ * to output_array[dest_row++]; these areas may overlap for duplication.
+ * The source and destination arrays must be at least as wide as num_cols.
+ */
+{
+  register JSAMPROW inptr, outptr;
+#ifdef FMEMCOPY
+  register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE));
+#else
+  register JDIMENSION count;
+#endif
+  register int row;
+
+  input_array += source_row;
+  output_array += dest_row;
+
+  for (row = num_rows; row > 0; row--) {
+    inptr = *input_array++;
+    outptr = *output_array++;
+#ifdef FMEMCOPY
+    FMEMCOPY(outptr, inptr, count);
+#else
+    for (count = num_cols; count > 0; count--)
+      *outptr++ = *inptr++;  /* needn't bother with GETJSAMPLE() here */
+#endif
+  }
+}
+
+
+GLOBAL(void)
+jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
+     JDIMENSION num_blocks)
+/* Copy a row of coefficient blocks from one place to another. */
+{
+#ifdef FMEMCOPY
+  FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF)));
+#else
+  register JCOEFPTR inptr, outptr;
+  register long count;
+
+  inptr = (JCOEFPTR) input_row;
+  outptr = (JCOEFPTR) output_row;
+  for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) {
+    *outptr++ = *inptr++;
+  }
+#endif
+}
+
+
+GLOBAL(void)
+jzero_far (void FAR * target, size_t bytestozero)
+/* Zero out a chunk of FAR memory. */
+/* This might be sample-array data, block-array data, or alloc_large data. */
+{
+#ifdef FMEMZERO
+  FMEMZERO(target, bytestozero);
+#else
+  register char FAR * ptr = (char FAR *) target;
+  register size_t count;
+
+  for (count = bytestozero; count > 0; count--) {
+    *ptr++ = 0;
+  }
+#endif
+}
diff --git a/Utilities/ITK/Utilities/itkjpeg/jversion.h b/Utilities/ITK/Utilities/itkjpeg/jversion.h
new file mode 100644
index 0000000000000000000000000000000000000000..95d81303031a23a9c4a99b7bdb1005e3d3ff175b
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/jversion.h
@@ -0,0 +1,14 @@
+/*
+ * jversion.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains software version identification.
+ */
+
+
+#define JVERSION  "6b  27-Mar-1998"
+
+#define JCOPYRIGHT  "Copyright (C) 1998, Thomas G. Lane"
diff --git a/Utilities/ITK/Utilities/itkjpeg/libjpeg.doc b/Utilities/ITK/Utilities/itkjpeg/libjpeg.doc
new file mode 100644
index 0000000000000000000000000000000000000000..20ce7b48192ca3d118cc7053d4f8a0ad9b42fd4f
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/libjpeg.doc
@@ -0,0 +1,3011 @@
+USING THE IJG JPEG LIBRARY
+
+Copyright (C) 1994-1998, Thomas G. Lane.
+This file is part of the Independent JPEG Group's software.
+For conditions of distribution and use, see the accompanying README file.
+
+
+This file describes how to use the IJG JPEG library within an application
+program.  Read it if you want to write a program that uses the library.
+
+The file example.c provides heavily commented skeleton code for calling the
+JPEG library.  Also see jpeglib.h (the include file to be used by application
+programs) for full details about data structures and function parameter lists.
+The library source code, of course, is the ultimate reference.
+
+Note that there have been *major* changes from the application interface
+presented by IJG version 4 and earlier versions.  The old design had several
+inherent limitations, and it had accumulated a lot of cruft as we added
+features while trying to minimize application-interface changes.  We have
+sacrificed backward compatibility in the version 5 rewrite, but we think the
+improvements justify this.
+
+
+TABLE OF CONTENTS
+-----------------
+
+Overview:
+	Functions provided by the library
+	Outline of typical usage
+Basic library usage:
+	Data formats
+	Compression details
+	Decompression details
+	Mechanics of usage: include files, linking, etc
+Advanced features:
+	Compression parameter selection
+	Decompression parameter selection
+	Special color spaces
+	Error handling
+	Compressed data handling (source and destination managers)
+	I/O suspension
+	Progressive JPEG support
+	Buffered-image mode
+	Abbreviated datastreams and multiple images
+	Special markers
+	Raw (downsampled) image data
+	Really raw data: DCT coefficients
+	Progress monitoring
+	Memory management
+	Memory usage
+	Library compile-time options
+	Portability considerations
+	Notes for MS-DOS implementors
+
+You should read at least the overview and basic usage sections before trying
+to program with the library.  The sections on advanced features can be read
+if and when you need them.
+
+
+OVERVIEW
+========
+
+Functions provided by the library
+---------------------------------
+
+The IJG JPEG library provides C code to read and write JPEG-compressed image
+files.  The surrounding application program receives or supplies image data a
+scanline at a time, using a straightforward uncompressed image format.  All
+details of color conversion and other preprocessing/postprocessing can be
+handled by the library.
+
+The library includes a substantial amount of code that is not covered by the
+JPEG standard but is necessary for typical applications of JPEG.  These
+functions preprocess the image before JPEG compression or postprocess it after
+decompression.  They include colorspace conversion, downsampling/upsampling,
+and color quantization.  The application indirectly selects use of this code
+by specifying the format in which it wishes to supply or receive image data.
+For example, if colormapped output is requested, then the decompression
+library automatically invokes color quantization.
+
+A wide range of quality vs. speed tradeoffs are possible in JPEG processing,
+and even more so in decompression postprocessing.  The decompression library
+provides multiple implementations that cover most of the useful tradeoffs,
+ranging from very-high-quality down to fast-preview operation.  On the
+compression side we have generally not provided low-quality choices, since
+compression is normally less time-critical.  It should be understood that the
+low-quality modes may not meet the JPEG standard's accuracy requirements;
+nonetheless, they are useful for viewers.
+
+A word about functions *not* provided by the library.  We handle a subset of
+the ISO JPEG standard; most baseline, extended-sequential, and progressive
+JPEG processes are supported.  (Our subset includes all features now in common
+use.)  Unsupported ISO options include:
+	* Hierarchical storage
+	* Arithmetic entropy coding (unsupported for legal reasons)
+	* DNL marker
+	* Nonintegral subsampling ratios
+We support both 8- and 12-bit data precision, but this is a compile-time
+choice rather than a run-time choice; hence it is difficult to use both
+precisions in a single application.
+
+By itself, the library handles only interchange JPEG datastreams --- in
+particular the widely used JFIF file format.  The library can be used by
+surrounding code to process interchange or abbreviated JPEG datastreams that
+are embedded in more complex file formats.  (For example, this library is
+used by the free LIBTIFF library to support JPEG compression in TIFF.)
+
+
+Outline of typical usage
+------------------------
+
+The rough outline of a JPEG compression operation is:
+
+	Allocate and initialize a JPEG compression object
+	Specify the destination for the compressed data (eg, a file)
+	Set parameters for compression, including image size & colorspace
+	jpeg_start_compress(...);
+	while (scan lines remain to be written)
+		jpeg_write_scanlines(...);
+	jpeg_finish_compress(...);
+	Release the JPEG compression object
+
+A JPEG compression object holds parameters and working state for the JPEG
+library.  We make creation/destruction of the object separate from starting
+or finishing compression of an image; the same object can be re-used for a
+series of image compression operations.  This makes it easy to re-use the
+same parameter settings for a sequence of images.  Re-use of a JPEG object
+also has important implications for processing abbreviated JPEG datastreams,
+as discussed later.
+
+The image data to be compressed is supplied to jpeg_write_scanlines() from
+in-memory buffers.  If the application is doing file-to-file compression,
+reading image data from the source file is the application's responsibility.
+The library emits compressed data by calling a "data destination manager",
+which typically will write the data into a file; but the application can
+provide its own destination manager to do something else.
+
+Similarly, the rough outline of a JPEG decompression operation is:
+
+	Allocate and initialize a JPEG decompression object
+	Specify the source of the compressed data (eg, a file)
+	Call jpeg_read_header() to obtain image info
+	Set parameters for decompression
+	jpeg_start_decompress(...);
+	while (scan lines remain to be read)
+		jpeg_read_scanlines(...);
+	jpeg_finish_decompress(...);
+	Release the JPEG decompression object
+
+This is comparable to the compression outline except that reading the
+datastream header is a separate step.  This is helpful because information
+about the image's size, colorspace, etc is available when the application
+selects decompression parameters.  For example, the application can choose an
+output scaling ratio that will fit the image into the available screen size.
+
+The decompression library obtains compressed data by calling a data source
+manager, which typically will read the data from a file; but other behaviors
+can be obtained with a custom source manager.  Decompressed data is delivered
+into in-memory buffers passed to jpeg_read_scanlines().
+
+It is possible to abort an incomplete compression or decompression operation
+by calling jpeg_abort(); or, if you do not need to retain the JPEG object,
+simply release it by calling jpeg_destroy().
+
+JPEG compression and decompression objects are two separate struct types.
+However, they share some common fields, and certain routines such as
+jpeg_destroy() can work on either type of object.
+
+The JPEG library has no static variables: all state is in the compression
+or decompression object.  Therefore it is possible to process multiple
+compression and decompression operations concurrently, using multiple JPEG
+objects.
+
+Both compression and decompression can be done in an incremental memory-to-
+memory fashion, if suitable source/destination managers are used.  See the
+section on "I/O suspension" for more details.
+
+
+BASIC LIBRARY USAGE
+===================
+
+Data formats
+------------
+
+Before diving into procedural details, it is helpful to understand the
+image data format that the JPEG library expects or returns.
+
+The standard input image format is a rectangular array of pixels, with each
+pixel having the same number of "component" or "sample" values (color
+channels).  You must specify how many components there are and the colorspace
+interpretation of the components.  Most applications will use RGB data
+(three components per pixel) or grayscale data (one component per pixel).
+PLEASE NOTE THAT RGB DATA IS THREE SAMPLES PER PIXEL, GRAYSCALE ONLY ONE.
+A remarkable number of people manage to miss this, only to find that their
+programs don't work with grayscale JPEG files.
+
+There is no provision for colormapped input.  JPEG files are always full-color
+or full grayscale (or sometimes another colorspace such as CMYK).  You can
+feed in a colormapped image by expanding it to full-color format.  However
+JPEG often doesn't work very well with source data that has been colormapped,
+because of dithering noise.  This is discussed in more detail in the JPEG FAQ
+and the other references mentioned in the README file.
+
+Pixels are stored by scanlines, with each scanline running from left to
+right.  The component values for each pixel are adjacent in the row; for
+example, R,G,B,R,G,B,R,G,B,... for 24-bit RGB color.  Each scanline is an
+array of data type JSAMPLE --- which is typically "unsigned char", unless
+you've changed jmorecfg.h.  (You can also change the RGB pixel layout, say
+to B,G,R order, by modifying jmorecfg.h.  But see the restrictions listed in
+that file before doing so.)
+
+A 2-D array of pixels is formed by making a list of pointers to the starts of
+scanlines; so the scanlines need not be physically adjacent in memory.  Even
+if you process just one scanline at a time, you must make a one-element
+pointer array to conform to this structure.  Pointers to JSAMPLE rows are of
+type JSAMPROW, and the pointer to the pointer array is of type JSAMPARRAY.
+
+The library accepts or supplies one or more complete scanlines per call.
+It is not possible to process part of a row at a time.  Scanlines are always
+processed top-to-bottom.  You can process an entire image in one call if you
+have it all in memory, but usually it's simplest to process one scanline at
+a time.
+
+For best results, source data values should have the precision specified by
+BITS_IN_JSAMPLE (normally 8 bits).  For instance, if you choose to compress
+data that's only 6 bits/channel, you should left-justify each value in a
+byte before passing it to the compressor.  If you need to compress data
+that has more than 8 bits/channel, compile with BITS_IN_JSAMPLE = 12.
+(See "Library compile-time options", later.)
+
+
+The data format returned by the decompressor is the same in all details,
+except that colormapped output is supported.  (Again, a JPEG file is never
+colormapped.  But you can ask the decompressor to perform on-the-fly color
+quantization to deliver colormapped output.)  If you request colormapped
+output then the returned data array contains a single JSAMPLE per pixel;
+its value is an index into a color map.  The color map is represented as
+a 2-D JSAMPARRAY in which each row holds the values of one color component,
+that is, colormap[i][j] is the value of the i'th color component for pixel
+value (map index) j.  Note that since the colormap indexes are stored in
+JSAMPLEs, the maximum number of colors is limited by the size of JSAMPLE
+(ie, at most 256 colors for an 8-bit JPEG library).
+
+
+Compression details
+-------------------
+
+Here we revisit the JPEG compression outline given in the overview.
+
+1. Allocate and initialize a JPEG compression object.
+
+A JPEG compression object is a "struct jpeg_compress_struct".  (It also has
+a bunch of subsidiary structures which are allocated via malloc(), but the
+application doesn't control those directly.)  This struct can be just a local
+variable in the calling routine, if a single routine is going to execute the
+whole JPEG compression sequence.  Otherwise it can be static or allocated
+from malloc().
+
+You will also need a structure representing a JPEG error handler.  The part
+of this that the library cares about is a "struct jpeg_error_mgr".  If you
+are providing your own error handler, you'll typically want to embed the
+jpeg_error_mgr struct in a larger structure; this is discussed later under
+"Error handling".  For now we'll assume you are just using the default error
+handler.  The default error handler will print JPEG error/warning messages
+on stderr, and it will call exit() if a fatal error occurs.
+
+You must initialize the error handler structure, store a pointer to it into
+the JPEG object's "err" field, and then call jpeg_create_compress() to
+initialize the rest of the JPEG object.
+
+Typical code for this step, if you are using the default error handler, is
+
+	struct jpeg_compress_struct cinfo;
+	struct jpeg_error_mgr jerr;
+	...
+	cinfo.err = jpeg_std_error(&jerr);
+	jpeg_create_compress(&cinfo);
+
+jpeg_create_compress allocates a small amount of memory, so it could fail
+if you are out of memory.  In that case it will exit via the error handler;
+that's why the error handler must be initialized first.
+
+
+2. Specify the destination for the compressed data (eg, a file).
+
+As previously mentioned, the JPEG library delivers compressed data to a
+"data destination" module.  The library includes one data destination
+module which knows how to write to a stdio stream.  You can use your own
+destination module if you want to do something else, as discussed later.
+
+If you use the standard destination module, you must open the target stdio
+stream beforehand.  Typical code for this step looks like:
+
+	FILE * outfile;
+	...
+	if ((outfile = fopen(filename, "wb")) == NULL) {
+	    fprintf(stderr, "can't open %s\n", filename);
+	    exit(1);
+	}
+	jpeg_stdio_dest(&cinfo, outfile);
+
+where the last line invokes the standard destination module.
+
+WARNING: it is critical that the binary compressed data be delivered to the
+output file unchanged.  On non-Unix systems the stdio library may perform
+newline translation or otherwise corrupt binary data.  To suppress this
+behavior, you may need to use a "b" option to fopen (as shown above), or use
+setmode() or another routine to put the stdio stream in binary mode.  See
+cjpeg.c and djpeg.c for code that has been found to work on many systems.
+
+You can select the data destination after setting other parameters (step 3),
+if that's more convenient.  You may not change the destination between
+calling jpeg_start_compress() and jpeg_finish_compress().
+
+
+3. Set parameters for compression, including image size & colorspace.
+
+You must supply information about the source image by setting the following
+fields in the JPEG object (cinfo structure):
+
+	image_width		Width of image, in pixels
+	image_height		Height of image, in pixels
+	input_components	Number of color channels (samples per pixel)
+	in_color_space		Color space of source image
+
+The image dimensions are, hopefully, obvious.  JPEG supports image dimensions
+of 1 to 64K pixels in either direction.  The input color space is typically
+RGB or grayscale, and input_components is 3 or 1 accordingly.  (See "Special
+color spaces", later, for more info.)  The in_color_space field must be
+assigned one of the J_COLOR_SPACE enum constants, typically JCS_RGB or
+JCS_GRAYSCALE.
+
+JPEG has a large number of compression parameters that determine how the
+image is encoded.  Most applications don't need or want to know about all
+these parameters.  You can set all the parameters to reasonable defaults by
+calling jpeg_set_defaults(); then, if there are particular values you want
+to change, you can do so after that.  The "Compression parameter selection"
+section tells about all the parameters.
+
+You must set in_color_space correctly before calling jpeg_set_defaults(),
+because the defaults depend on the source image colorspace.  However the
+other three source image parameters need not be valid until you call
+jpeg_start_compress().  There's no harm in calling jpeg_set_defaults() more
+than once, if that happens to be convenient.
+
+Typical code for a 24-bit RGB source image is
+
+	cinfo.image_width = Width; 	/* image width and height, in pixels */
+	cinfo.image_height = Height;
+	cinfo.input_components = 3;	/* # of color components per pixel */
+	cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+
+	jpeg_set_defaults(&cinfo);
+	/* Make optional parameter settings here */
+
+
+4. jpeg_start_compress(...);
+
+After you have established the data destination and set all the necessary
+source image info and other parameters, call jpeg_start_compress() to begin
+a compression cycle.  This will initialize internal state, allocate working
+storage, and emit the first few bytes of the JPEG datastream header.
+
+Typical code:
+
+	jpeg_start_compress(&cinfo, TRUE);
+
+The "TRUE" parameter ensures that a complete JPEG interchange datastream
+will be written.  This is appropriate in most cases.  If you think you might
+want to use an abbreviated datastream, read the section on abbreviated
+datastreams, below.
+
+Once you have called jpeg_start_compress(), you may not alter any JPEG
+parameters or other fields of the JPEG object until you have completed
+the compression cycle.
+
+
+5. while (scan lines remain to be written)
+	jpeg_write_scanlines(...);
+
+Now write all the required image data by calling jpeg_write_scanlines()
+one or more times.  You can pass one or more scanlines in each call, up
+to the total image height.  In most applications it is convenient to pass
+just one or a few scanlines at a time.  The expected format for the passed
+data is discussed under "Data formats", above.
+
+Image data should be written in top-to-bottom scanline order.  The JPEG spec
+contains some weasel wording about how top and bottom are application-defined
+terms (a curious interpretation of the English language...) but if you want
+your files to be compatible with everyone else's, you WILL use top-to-bottom
+order.  If the source data must be read in bottom-to-top order, you can use
+the JPEG library's virtual array mechanism to invert the data efficiently.
+Examples of this can be found in the sample application cjpeg.
+
+The library maintains a count of the number of scanlines written so far
+in the next_scanline field of the JPEG object.  Usually you can just use
+this variable as the loop counter, so that the loop test looks like
+"while (cinfo.next_scanline < cinfo.image_height)".
+
+Code for this step depends heavily on the way that you store the source data.
+example.c shows the following code for the case of a full-size 2-D source
+array containing 3-byte RGB pixels:
+
+	JSAMPROW row_pointer[1];	/* pointer to a single row */
+	int row_stride;			/* physical row width in buffer */
+
+	row_stride = image_width * 3;	/* JSAMPLEs per row in image_buffer */
+
+	while (cinfo.next_scanline < cinfo.image_height) {
+	    row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+	    jpeg_write_scanlines(&cinfo, row_pointer, 1);
+	}
+
+jpeg_write_scanlines() returns the number of scanlines actually written.
+This will normally be equal to the number passed in, so you can usually
+ignore the return value.  It is different in just two cases:
+  * If you try to write more scanlines than the declared image height,
+    the additional scanlines are ignored.
+  * If you use a suspending data destination manager, output buffer overrun
+    will cause the compressor to return before accepting all the passed lines.
+    This feature is discussed under "I/O suspension", below.  The normal
+    stdio destination manager will NOT cause this to happen.
+In any case, the return value is the same as the change in the value of
+next_scanline.
+
+
+6. jpeg_finish_compress(...);
+
+After all the image data has been written, call jpeg_finish_compress() to
+complete the compression cycle.  This step is ESSENTIAL to ensure that the
+last bufferload of data is written to the data destination.
+jpeg_finish_compress() also releases working memory associated with the JPEG
+object.
+
+Typical code:
+
+	jpeg_finish_compress(&cinfo);
+
+If using the stdio destination manager, don't forget to close the output
+stdio stream (if necessary) afterwards.
+
+If you have requested a multi-pass operating mode, such as Huffman code
+optimization, jpeg_finish_compress() will perform the additional passes using
+data buffered by the first pass.  In this case jpeg_finish_compress() may take
+quite a while to complete.  With the default compression parameters, this will
+not happen.
+
+It is an error to call jpeg_finish_compress() before writing the necessary
+total number of scanlines.  If you wish to abort compression, call
+jpeg_abort() as discussed below.
+
+After completing a compression cycle, you may dispose of the JPEG object
+as discussed next, or you may use it to compress another image.  In that case
+return to step 2, 3, or 4 as appropriate.  If you do not change the
+destination manager, the new datastream will be written to the same target.
+If you do not change any JPEG parameters, the new datastream will be written
+with the same parameters as before.  Note that you can change the input image
+dimensions freely between cycles, but if you change the input colorspace, you
+should call jpeg_set_defaults() to adjust for the new colorspace; and then
+you'll need to repeat all of step 3.
+
+
+7. Release the JPEG compression object.
+
+When you are done with a JPEG compression object, destroy it by calling
+jpeg_destroy_compress().  This will free all subsidiary memory (regardless of
+the previous state of the object).  Or you can call jpeg_destroy(), which
+works for either compression or decompression objects --- this may be more
+convenient if you are sharing code between compression and decompression
+cases.  (Actually, these routines are equivalent except for the declared type
+of the passed pointer.  To avoid gripes from ANSI C compilers, jpeg_destroy()
+should be passed a j_common_ptr.)
+
+If you allocated the jpeg_compress_struct structure from malloc(), freeing
+it is your responsibility --- jpeg_destroy() won't.  Ditto for the error
+handler structure.
+
+Typical code:
+
+	jpeg_destroy_compress(&cinfo);
+
+
+8. Aborting.
+
+If you decide to abort a compression cycle before finishing, you can clean up
+in either of two ways:
+
+* If you don't need the JPEG object any more, just call
+  jpeg_destroy_compress() or jpeg_destroy() to release memory.  This is
+  legitimate at any point after calling jpeg_create_compress() --- in fact,
+  it's safe even if jpeg_create_compress() fails.
+
+* If you want to re-use the JPEG object, call jpeg_abort_compress(), or call
+  jpeg_abort() which works on both compression and decompression objects.
+  This will return the object to an idle state, releasing any working memory.
+  jpeg_abort() is allowed at any time after successful object creation.
+
+Note that cleaning up the data destination, if required, is your
+responsibility; neither of these routines will call term_destination().
+(See "Compressed data handling", below, for more about that.)
+
+jpeg_destroy() and jpeg_abort() are the only safe calls to make on a JPEG
+object that has reported an error by calling error_exit (see "Error handling"
+for more info).  The internal state of such an object is likely to be out of
+whack.  Either of these two routines will return the object to a known state.
+
+
+Decompression details
+---------------------
+
+Here we revisit the JPEG decompression outline given in the overview.
+
+1. Allocate and initialize a JPEG decompression object.
+
+This is just like initialization for compression, as discussed above,
+except that the object is a "struct jpeg_decompress_struct" and you
+call jpeg_create_decompress().  Error handling is exactly the same.
+
+Typical code:
+
+	struct jpeg_decompress_struct cinfo;
+	struct jpeg_error_mgr jerr;
+	...
+	cinfo.err = jpeg_std_error(&jerr);
+	jpeg_create_decompress(&cinfo);
+
+(Both here and in the IJG code, we usually use variable name "cinfo" for
+both compression and decompression objects.)
+
+
+2. Specify the source of the compressed data (eg, a file).
+
+As previously mentioned, the JPEG library reads compressed data from a "data
+source" module.  The library includes one data source module which knows how
+to read from a stdio stream.  You can use your own source module if you want
+to do something else, as discussed later.
+
+If you use the standard source module, you must open the source stdio stream
+beforehand.  Typical code for this step looks like:
+
+	FILE * infile;
+	...
+	if ((infile = fopen(filename, "rb")) == NULL) {
+	    fprintf(stderr, "can't open %s\n", filename);
+	    exit(1);
+	}
+	jpeg_stdio_src(&cinfo, infile);
+
+where the last line invokes the standard source module.
+
+WARNING: it is critical that the binary compressed data be read unchanged.
+On non-Unix systems the stdio library may perform newline translation or
+otherwise corrupt binary data.  To suppress this behavior, you may need to use
+a "b" option to fopen (as shown above), or use setmode() or another routine to
+put the stdio stream in binary mode.  See cjpeg.c and djpeg.c for code that
+has been found to work on many systems.
+
+You may not change the data source between calling jpeg_read_header() and
+jpeg_finish_decompress().  If you wish to read a series of JPEG images from
+a single source file, you should repeat the jpeg_read_header() to
+jpeg_finish_decompress() sequence without reinitializing either the JPEG
+object or the data source module; this prevents buffered input data from
+being discarded.
+
+
+3. Call jpeg_read_header() to obtain image info.
+
+Typical code for this step is just
+
+	jpeg_read_header(&cinfo, TRUE);
+
+This will read the source datastream header markers, up to the beginning
+of the compressed data proper.  On return, the image dimensions and other
+info have been stored in the JPEG object.  The application may wish to
+consult this information before selecting decompression parameters.
+
+More complex code is necessary if
+  * A suspending data source is used --- in that case jpeg_read_header()
+    may return before it has read all the header data.  See "I/O suspension",
+    below.  The normal stdio source manager will NOT cause this to happen.
+  * Abbreviated JPEG files are to be processed --- see the section on
+    abbreviated datastreams.  Standard applications that deal only in
+    interchange JPEG files need not be concerned with this case either.
+
+It is permissible to stop at this point if you just wanted to find out the
+image dimensions and other header info for a JPEG file.  In that case,
+call jpeg_destroy() when you are done with the JPEG object, or call
+jpeg_abort() to return it to an idle state before selecting a new data
+source and reading another header.
+
+
+4. Set parameters for decompression.
+
+jpeg_read_header() sets appropriate default decompression parameters based on
+the properties of the image (in particular, its colorspace).  However, you
+may well want to alter these defaults before beginning the decompression.
+For example, the default is to produce full color output from a color file.
+If you want colormapped output you must ask for it.  Other options allow the
+returned image to be scaled and allow various speed/quality tradeoffs to be
+selected.  "Decompression parameter selection", below, gives details.
+
+If the defaults are appropriate, nothing need be done at this step.
+
+Note that all default values are set by each call to jpeg_read_header().
+If you reuse a decompression object, you cannot expect your parameter
+settings to be preserved across cycles, as you can for compression.
+You must set desired parameter values each time.
+
+
+5. jpeg_start_decompress(...);
+
+Once the parameter values are satisfactory, call jpeg_start_decompress() to
+begin decompression.  This will initialize internal state, allocate working
+memory, and prepare for returning data.
+
+Typical code is just
+
+	jpeg_start_decompress(&cinfo);
+
+If you have requested a multi-pass operating mode, such as 2-pass color
+quantization, jpeg_start_decompress() will do everything needed before data
+output can begin.  In this case jpeg_start_decompress() may take quite a while
+to complete.  With a single-scan (non progressive) JPEG file and default
+decompression parameters, this will not happen; jpeg_start_decompress() will
+return quickly.
+
+After this call, the final output image dimensions, including any requested
+scaling, are available in the JPEG object; so is the selected colormap, if
+colormapped output has been requested.  Useful fields include
+
+	output_width		image width and height, as scaled
+	output_height
+	out_color_components	# of color components in out_color_space
+	output_components	# of color components returned per pixel
+	colormap		the selected colormap, if any
+	actual_number_of_colors		number of entries in colormap
+
+output_components is 1 (a colormap index) when quantizing colors; otherwise it
+equals out_color_components.  It is the number of JSAMPLE values that will be
+emitted per pixel in the output arrays.
+
+Typically you will need to allocate data buffers to hold the incoming image.
+You will need output_width * output_components JSAMPLEs per scanline in your
+output buffer, and a total of output_height scanlines will be returned.
+
+Note: if you are using the JPEG library's internal memory manager to allocate
+data buffers (as djpeg does), then the manager's protocol requires that you
+request large buffers *before* calling jpeg_start_decompress().  This is a
+little tricky since the output_XXX fields are not normally valid then.  You
+can make them valid by calling jpeg_calc_output_dimensions() after setting the
+relevant parameters (scaling, output color space, and quantization flag).
+
+
+6. while (scan lines remain to be read)
+	jpeg_read_scanlines(...);
+
+Now you can read the decompressed image data by calling jpeg_read_scanlines()
+one or more times.  At each call, you pass in the maximum number of scanlines
+to be read (ie, the height of your working buffer); jpeg_read_scanlines()
+will return up to that many lines.  The return value is the number of lines
+actually read.  The format of the returned data is discussed under "Data
+formats", above.  Don't forget that grayscale and color JPEGs will return
+different data formats!
+
+Image data is returned in top-to-bottom scanline order.  If you must write
+out the image in bottom-to-top order, you can use the JPEG library's virtual
+array mechanism to invert the data efficiently.  Examples of this can be
+found in the sample application djpeg.
+
+The library maintains a count of the number of scanlines returned so far
+in the output_scanline field of the JPEG object.  Usually you can just use
+this variable as the loop counter, so that the loop test looks like
+"while (cinfo.output_scanline < cinfo.output_height)".  (Note that the test
+should NOT be against image_height, unless you never use scaling.  The
+image_height field is the height of the original unscaled image.)
+The return value always equals the change in the value of output_scanline.
+
+If you don't use a suspending data source, it is safe to assume that
+jpeg_read_scanlines() reads at least one scanline per call, until the
+bottom of the image has been reached.
+
+If you use a buffer larger than one scanline, it is NOT safe to assume that
+jpeg_read_scanlines() fills it.  (The current implementation returns only a
+few scanlines per call, no matter how large a buffer you pass.)  So you must
+always provide a loop that calls jpeg_read_scanlines() repeatedly until the
+whole image has been read.
+
+
+7. jpeg_finish_decompress(...);
+
+After all the image data has been read, call jpeg_finish_decompress() to
+complete the decompression cycle.  This causes working memory associated
+with the JPEG object to be released.
+
+Typical code:
+
+	jpeg_finish_decompress(&cinfo);
+
+If using the stdio source manager, don't forget to close the source stdio
+stream if necessary.
+
+It is an error to call jpeg_finish_decompress() before reading the correct
+total number of scanlines.  If you wish to abort decompression, call
+jpeg_abort() as discussed below.
+
+After completing a decompression cycle, you may dispose of the JPEG object as
+discussed next, or you may use it to decompress another image.  In that case
+return to step 2 or 3 as appropriate.  If you do not change the source
+manager, the next image will be read from the same source.
+
+
+8. Release the JPEG decompression object.
+
+When you are done with a JPEG decompression object, destroy it by calling
+jpeg_destroy_decompress() or jpeg_destroy().  The previous discussion of
+destroying compression objects applies here too.
+
+Typical code:
+
+	jpeg_destroy_decompress(&cinfo);
+
+
+9. Aborting.
+
+You can abort a decompression cycle by calling jpeg_destroy_decompress() or
+jpeg_destroy() if you don't need the JPEG object any more, or
+jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object.
+The previous discussion of aborting compression cycles applies here too.
+
+
+Mechanics of usage: include files, linking, etc
+-----------------------------------------------
+
+Applications using the JPEG library should include the header file jpeglib.h
+to obtain declarations of data types and routines.  Before including
+jpeglib.h, include system headers that define at least the typedefs FILE and
+size_t.  On ANSI-conforming systems, including <stdio.h> is sufficient; on
+older Unix systems, you may need <sys/types.h> to define size_t.
+
+If the application needs to refer to individual JPEG library error codes, also
+include jerror.h to define those symbols.
+
+jpeglib.h indirectly includes the files jconfig.h and jmorecfg.h.  If you are
+installing the JPEG header files in a system directory, you will want to
+install all four files: jpeglib.h, jerror.h, jconfig.h, jmorecfg.h.
+
+The most convenient way to include the JPEG code into your executable program
+is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix
+machines) and reference it at your link step.  If you use only half of the
+library (only compression or only decompression), only that much code will be
+included from the library, unless your linker is hopelessly brain-damaged.
+The supplied makefiles build libjpeg.a automatically (see install.doc).
+
+While you can build the JPEG library as a shared library if the whim strikes
+you, we don't really recommend it.  The trouble with shared libraries is that
+at some point you'll probably try to substitute a new version of the library
+without recompiling the calling applications.  That generally doesn't work
+because the parameter struct declarations usually change with each new
+version.  In other words, the library's API is *not* guaranteed binary
+compatible across versions; we only try to ensure source-code compatibility.
+(In hindsight, it might have been smarter to hide the parameter structs from
+applications and introduce a ton of access functions instead.  Too late now,
+however.)
+
+On some systems your application may need to set up a signal handler to ensure
+that temporary files are deleted if the program is interrupted.  This is most
+critical if you are on MS-DOS and use the jmemdos.c memory manager back end;
+it will try to grab extended memory for temp files, and that space will NOT be
+freed automatically.  See cjpeg.c or djpeg.c for an example signal handler.
+
+It may be worth pointing out that the core JPEG library does not actually
+require the stdio library: only the default source/destination managers and
+error handler need it.  You can use the library in a stdio-less environment
+if you replace those modules and use jmemnobs.c (or another memory manager of
+your own devising).  More info about the minimum system library requirements
+may be found in jinclude.h.
+
+
+ADVANCED FEATURES
+=================
+
+Compression parameter selection
+-------------------------------
+
+This section describes all the optional parameters you can set for JPEG
+compression, as well as the "helper" routines provided to assist in this
+task.  Proper setting of some parameters requires detailed understanding
+of the JPEG standard; if you don't know what a parameter is for, it's best
+not to mess with it!  See REFERENCES in the README file for pointers to
+more info about JPEG.
+
+It's a good idea to call jpeg_set_defaults() first, even if you plan to set
+all the parameters; that way your code is more likely to work with future JPEG
+libraries that have additional parameters.  For the same reason, we recommend
+you use a helper routine where one is provided, in preference to twiddling
+cinfo fields directly.
+
+The helper routines are:
+
+jpeg_set_defaults (j_compress_ptr cinfo)
+	This routine sets all JPEG parameters to reasonable defaults, using
+	only the input image's color space (field in_color_space, which must
+	already be set in cinfo).  Many applications will only need to use
+	this routine and perhaps jpeg_set_quality().
+
+jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
+	Sets the JPEG file's colorspace (field jpeg_color_space) as specified,
+	and sets other color-space-dependent parameters appropriately.  See
+	"Special color spaces", below, before using this.  A large number of
+	parameters, including all per-component parameters, are set by this
+	routine; if you want to twiddle individual parameters you should call
+	jpeg_set_colorspace() before rather than after.
+
+jpeg_default_colorspace (j_compress_ptr cinfo)
+	Selects an appropriate JPEG colorspace based on cinfo->in_color_space,
+	and calls jpeg_set_colorspace().  This is actually a subroutine of
+	jpeg_set_defaults().  It's broken out in case you want to change
+	just the colorspace-dependent JPEG parameters.
+
+jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
+	Constructs JPEG quantization tables appropriate for the indicated
+	quality setting.  The quality value is expressed on the 0..100 scale
+	recommended by IJG (cjpeg's "-quality" switch uses this routine).
+	Note that the exact mapping from quality values to tables may change
+	in future IJG releases as more is learned about DCT quantization.
+	If the force_baseline parameter is TRUE, then the quantization table
+	entries are constrained to the range 1..255 for full JPEG baseline
+	compatibility.  In the current implementation, this only makes a
+	difference for quality settings below 25, and it effectively prevents
+	very small/low quality files from being generated.  The IJG decoder
+	is capable of reading the non-baseline files generated at low quality
+	settings when force_baseline is FALSE, but other decoders may not be.
+
+jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
+			 boolean force_baseline)
+	Same as jpeg_set_quality() except that the generated tables are the
+	sample tables given in the JPEC spec section K.1, multiplied by the
+	specified scale factor (which is expressed as a percentage; thus
+	scale_factor = 100 reproduces the spec's tables).  Note that larger
+	scale factors give lower quality.  This entry point is useful for
+	conforming to the Adobe PostScript DCT conventions, but we do not
+	recommend linear scaling as a user-visible quality scale otherwise.
+	force_baseline again constrains the computed table entries to 1..255.
+
+int jpeg_quality_scaling (int quality)
+	Converts a value on the IJG-recommended quality scale to a linear
+	scaling percentage.  Note that this routine may change or go away
+	in future releases --- IJG may choose to adopt a scaling method that
+	can't be expressed as a simple scalar multiplier, in which case the
+	premise of this routine collapses.  Caveat user.
+
+jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
+		      const unsigned int *basic_table,
+		      int scale_factor, boolean force_baseline)
+	Allows an arbitrary quantization table to be created.  which_tbl
+	indicates which table slot to fill.  basic_table points to an array
+	of 64 unsigned ints given in normal array order.  These values are
+	multiplied by scale_factor/100 and then clamped to the range 1..65535
+	(or to 1..255 if force_baseline is TRUE).
+	CAUTION: prior to library version 6a, jpeg_add_quant_table expected
+	the basic table to be given in JPEG zigzag order.  If you need to
+	write code that works with either older or newer versions of this
+	routine, you must check the library version number.  Something like
+	"#if JPEG_LIB_VERSION >= 61" is the right test.
+
+jpeg_simple_progression (j_compress_ptr cinfo)
+	Generates a default scan script for writing a progressive-JPEG file.
+	This is the recommended method of creating a progressive file,
+	unless you want to make a custom scan sequence.  You must ensure that
+	the JPEG color space is set correctly before calling this routine.
+
+jpeg_simple_lossless (j_compress_ptr cinfo, int predictor, int point_transform)
+	Generates a default scan script for writing a lossless-JPEG file.
+	This is the recommended method of creating a lossless file,
+	unless you want to make a custom scan sequence.  You must ensure that
+	the JPEG color space is set correctly before calling this routine.
+
+
+Compression parameters (cinfo fields) include:
+
+J_DCT_METHOD dct_method
+	Selects the algorithm used for the DCT step.  Choices are:
+		JDCT_ISLOW: slow but accurate integer algorithm
+		JDCT_IFAST: faster, less accurate integer method
+		JDCT_FLOAT: floating-point method
+		JDCT_DEFAULT: default method (normally JDCT_ISLOW)
+		JDCT_FASTEST: fastest method (normally JDCT_IFAST)
+	The FLOAT method is very slightly more accurate than the ISLOW method,
+	but may give different results on different machines due to varying
+	roundoff behavior.  The integer methods should give the same results
+	on all machines.  On machines with sufficiently fast FP hardware, the
+	floating-point method may also be the fastest.  The IFAST method is
+	considerably less accurate than the other two; its use is not
+	recommended if high quality is a concern.  JDCT_DEFAULT and
+	JDCT_FASTEST are macros configurable by each installation.
+
+J_COLOR_SPACE jpeg_color_space
+int num_components
+	The JPEG color space and corresponding number of components; see
+	"Special color spaces", below, for more info.  We recommend using
+	jpeg_set_color_space() if you want to change these.
+
+boolean optimize_coding
+	TRUE causes the compressor to compute optimal Huffman coding tables
+	for the image.  This requires an extra pass over the data and
+	therefore costs a good deal of space and time.  The default is
+	FALSE, which tells the compressor to use the supplied or default
+	Huffman tables.  In most cases optimal tables save only a few percent
+	of file size compared to the default tables.  Note that when this is
+	TRUE, you need not supply Huffman tables at all, and any you do
+	supply will be overwritten.
+
+unsigned int restart_interval
+int restart_in_rows
+	To emit restart markers in the JPEG file, set one of these nonzero.
+	Set restart_interval to specify the exact interval in MCU blocks.
+	Set restart_in_rows to specify the interval in MCU rows.  (If
+	restart_in_rows is not 0, then restart_interval is set after the
+	image width in MCUs is computed.)  Defaults are zero (no restarts).
+	One restart marker per MCU row is often a good choice.
+	NOTE: the overhead of restart markers is higher in grayscale JPEG
+	files than in color files, and MUCH higher in progressive JPEGs.
+	If you use restarts, you may want to use larger intervals in those
+	cases.
+
+const jpeg_scan_info * scan_info
+int num_scans
+	By default, scan_info is NULL; this causes the compressor to write a
+	single-scan sequential JPEG file.  If not NULL, scan_info points to
+	an array of scan definition records of length num_scans.  The
+	compressor will then write a JPEG file having one scan for each scan
+	definition record.  This is used to generate noninterleaved or
+	progressive JPEG files.  The library checks that the scan array
+	defines a valid JPEG scan sequence.  (jpeg_simple_progression creates
+	a suitable scan definition array for progressive JPEG.)  This is
+	discussed further under "Progressive JPEG support".
+
+int smoothing_factor
+	If non-zero, the input image is smoothed; the value should be 1 for
+	minimal smoothing to 100 for maximum smoothing.  Consult jcsample.c
+	for details of the smoothing algorithm.  The default is zero.
+
+boolean write_JFIF_header
+	If TRUE, a JFIF APP0 marker is emitted.  jpeg_set_defaults() and
+	jpeg_set_colorspace() set this TRUE if a JFIF-legal JPEG color space
+	(ie, YCbCr or grayscale) is selected, otherwise FALSE.
+
+UINT8 JFIF_major_version
+UINT8 JFIF_minor_version
+	The version number to be written into the JFIF marker.
+	jpeg_set_defaults() initializes the version to 1.01 (major=minor=1).
+	You should set it to 1.02 (major=1, minor=2) if you plan to write
+	any JFIF 1.02 extension markers.
+
+UINT8 density_unit
+UINT16 X_density
+UINT16 Y_density
+	The resolution information to be written into the JFIF marker;
+	not used otherwise.  density_unit may be 0 for unknown,
+	1 for dots/inch, or 2 for dots/cm.  The default values are 0,1,1
+	indicating square pixels of unknown size.
+
+boolean write_Adobe_marker
+	If TRUE, an Adobe APP14 marker is emitted.  jpeg_set_defaults() and
+	jpeg_set_colorspace() set this TRUE if JPEG color space RGB, CMYK,
+	or YCCK is selected, otherwise FALSE.  It is generally a bad idea
+	to set both write_JFIF_header and write_Adobe_marker.  In fact,
+	you probably shouldn't change the default settings at all --- the
+	default behavior ensures that the JPEG file's color space can be
+	recognized by the decoder.
+
+JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]
+	Pointers to coefficient quantization tables, one per table slot,
+	or NULL if no table is defined for a slot.  Usually these should
+	be set via one of the above helper routines; jpeg_add_quant_table()
+	is general enough to define any quantization table.  The other
+	routines will set up table slot 0 for luminance quality and table
+	slot 1 for chrominance.
+
+JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]
+JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]
+	Pointers to Huffman coding tables, one per table slot, or NULL if
+	no table is defined for a slot.  Slots 0 and 1 are filled with the
+	JPEG sample tables by jpeg_set_defaults().  If you need to allocate
+	more table structures, jpeg_alloc_huff_table() may be used.
+	Note that optimal Huffman tables can be computed for an image
+	by setting optimize_coding, as discussed above; there's seldom
+	any need to mess with providing your own Huffman tables.
+
+There are some additional cinfo fields which are not documented here
+because you currently can't change them; for example, you can't set
+arith_code TRUE because arithmetic coding is unsupported.
+
+
+Per-component parameters are stored in the struct cinfo.comp_info[i] for
+component number i.  Note that components here refer to components of the
+JPEG color space, *not* the source image color space.  A suitably large
+comp_info[] array is allocated by jpeg_set_defaults(); if you choose not
+to use that routine, it's up to you to allocate the array.
+
+int component_id
+	The one-byte identifier code to be recorded in the JPEG file for
+	this component.  For the standard color spaces, we recommend you
+	leave the default values alone.
+
+int h_samp_factor
+int v_samp_factor
+	Horizontal and vertical sampling factors for the component; must
+	be 1..4 according to the JPEG standard.  Note that larger sampling
+	factors indicate a higher-resolution component; many people find
+	this behavior quite unintuitive.  The default values are 2,2 for
+	luminance components and 1,1 for chrominance components, except
+	for grayscale where 1,1 is used.
+
+int quant_tbl_no
+	Quantization table number for component.  The default value is
+	0 for luminance components and 1 for chrominance components.
+
+int dc_tbl_no
+int ac_tbl_no
+	DC and AC entropy coding table numbers.  The default values are
+	0 for luminance components and 1 for chrominance components.
+
+int component_index
+	Must equal the component's index in comp_info[].  (Beginning in
+	release v6, the compressor library will fill this in automatically;
+	you don't have to.)
+
+
+Decompression parameter selection
+---------------------------------
+
+Decompression parameter selection is somewhat simpler than compression
+parameter selection, since all of the JPEG internal parameters are
+recorded in the source file and need not be supplied by the application.
+(Unless you are working with abbreviated files, in which case see
+"Abbreviated datastreams", below.)  Decompression parameters control
+the postprocessing done on the image to deliver it in a format suitable
+for the application's use.  Many of the parameters control speed/quality
+tradeoffs, in which faster decompression may be obtained at the price of
+a poorer-quality image.  The defaults select the highest quality (slowest)
+processing.
+
+The following fields in the JPEG object are set by jpeg_read_header() and
+may be useful to the application in choosing decompression parameters:
+
+JDIMENSION image_width			Width and height of image
+JDIMENSION image_height
+int num_components			Number of color components
+J_COLOR_SPACE jpeg_color_space		Colorspace of image
+boolean saw_JFIF_marker			TRUE if a JFIF APP0 marker was seen
+  UINT8 JFIF_major_version		Version information from JFIF marker
+  UINT8 JFIF_minor_version
+  UINT8 density_unit			Resolution data from JFIF marker
+  UINT16 X_density
+  UINT16 Y_density
+boolean saw_Adobe_marker		TRUE if an Adobe APP14 marker was seen
+  UINT8 Adobe_transform			Color transform code from Adobe marker
+
+The JPEG color space, unfortunately, is something of a guess since the JPEG
+standard proper does not provide a way to record it.  In practice most files
+adhere to the JFIF or Adobe conventions, and the decoder will recognize these
+correctly.  See "Special color spaces", below, for more info.
+
+
+The decompression parameters that determine the basic properties of the
+returned image are:
+
+J_COLOR_SPACE out_color_space
+	Output color space.  jpeg_read_header() sets an appropriate default
+	based on jpeg_color_space; typically it will be RGB or grayscale.
+	The application can change this field to request output in a different
+	colorspace.  For example, set it to JCS_GRAYSCALE to get grayscale
+	output from a color file.  (This is useful for previewing: grayscale
+	output is faster than full color since the color components need not
+	be processed.)  Note that not all possible color space transforms are
+	currently implemented; you may need to extend jdcolor.c if you want an
+	unusual conversion.
+
+unsigned int scale_num, scale_denom
+	Scale the image by the fraction scale_num/scale_denom.  Default is
+	1/1, or no scaling.  Currently, the only supported scaling ratios
+	are 1/1, 1/2, 1/4, and 1/8.  (The library design allows for arbitrary
+	scaling ratios but this is not likely to be implemented any time soon.)
+	Smaller scaling ratios permit significantly faster decoding since
+	fewer pixels need be processed and a simpler IDCT method can be used.
+
+boolean quantize_colors
+	If set TRUE, colormapped output will be delivered.  Default is FALSE,
+	meaning that full-color output will be delivered.
+
+The next three parameters are relevant only if quantize_colors is TRUE.
+
+int desired_number_of_colors
+	Maximum number of colors to use in generating a library-supplied color
+	map (the actual number of colors is returned in a different field).
+	Default 256.  Ignored when the application supplies its own color map.
+
+boolean two_pass_quantize
+	If TRUE, an extra pass over the image is made to select a custom color
+	map for the image.  This usually looks a lot better than the one-size-
+	fits-all colormap that is used otherwise.  Default is TRUE.  Ignored
+	when the application supplies its own color map.
+
+J_DITHER_MODE dither_mode
+	Selects color dithering method.  Supported values are:
+		JDITHER_NONE	no dithering: fast, very low quality
+		JDITHER_ORDERED	ordered dither: moderate speed and quality
+		JDITHER_FS	Floyd-Steinberg dither: slow, high quality
+	Default is JDITHER_FS.  (At present, ordered dither is implemented
+	only in the single-pass, standard-colormap case.  If you ask for
+	ordered dither when two_pass_quantize is TRUE or when you supply
+	an external color map, you'll get F-S dithering.)
+
+When quantize_colors is TRUE, the target color map is described by the next
+two fields.  colormap is set to NULL by jpeg_read_header().  The application
+can supply a color map by setting colormap non-NULL and setting
+actual_number_of_colors to the map size.  Otherwise, jpeg_start_decompress()
+selects a suitable color map and sets these two fields itself.
+[Implementation restriction: at present, an externally supplied colormap is
+only accepted for 3-component output color spaces.]
+
+JSAMPARRAY colormap
+	The color map, represented as a 2-D pixel array of out_color_components
+	rows and actual_number_of_colors columns.  Ignored if not quantizing.
+	CAUTION: if the JPEG library creates its own colormap, the storage
+	pointed to by this field is released by jpeg_finish_decompress().
+	Copy the colormap somewhere else first, if you want to save it.
+
+int actual_number_of_colors
+	The number of colors in the color map.
+
+Additional decompression parameters that the application may set include:
+
+J_DCT_METHOD dct_method
+	Selects the algorithm used for the DCT step.  Choices are the same
+	as described above for compression.
+
+boolean do_fancy_upsampling
+	If TRUE, do careful upsampling of chroma components.  If FALSE,
+	a faster but sloppier method is used.  Default is TRUE.  The visual
+	impact of the sloppier method is often very small.
+
+boolean do_block_smoothing
+	If TRUE, interblock smoothing is applied in early stages of decoding
+	progressive JPEG files; if FALSE, not.  Default is TRUE.  Early
+	progression stages look "fuzzy" with smoothing, "blocky" without.
+	In any case, block smoothing ceases to be applied after the first few
+	AC coefficients are known to full accuracy, so it is relevant only
+	when using buffered-image mode for progressive images.
+
+boolean enable_1pass_quant
+boolean enable_external_quant
+boolean enable_2pass_quant
+	These are significant only in buffered-image mode, which is
+	described in its own section below.
+
+
+The output image dimensions are given by the following fields.  These are
+computed from the source image dimensions and the decompression parameters
+by jpeg_start_decompress().  You can also call jpeg_calc_output_dimensions()
+to obtain the values that will result from the current parameter settings.
+This can be useful if you are trying to pick a scaling ratio that will get
+close to a desired target size.  It's also important if you are using the
+JPEG library's memory manager to allocate output buffer space, because you
+are supposed to request such buffers *before* jpeg_start_decompress().
+
+JDIMENSION output_width		Actual dimensions of output image.
+JDIMENSION output_height
+int out_color_components	Number of color components in out_color_space.
+int output_components		Number of color components returned.
+int rec_outbuf_height		Recommended height of scanline buffer.
+
+When quantizing colors, output_components is 1, indicating a single color map
+index per pixel.  Otherwise it equals out_color_components.  The output arrays
+are required to be output_width * output_components JSAMPLEs wide.
+
+rec_outbuf_height is the recommended minimum height (in scanlines) of the
+buffer passed to jpeg_read_scanlines().  If the buffer is smaller, the
+library will still work, but time will be wasted due to unnecessary data
+copying.  In high-quality modes, rec_outbuf_height is always 1, but some
+faster, lower-quality modes set it to larger values (typically 2 to 4).
+If you are going to ask for a high-speed processing mode, you may as well
+go to the trouble of honoring rec_outbuf_height so as to avoid data copying.
+(An output buffer larger than rec_outbuf_height lines is OK, but won't
+provide any material speed improvement over that height.)
+
+
+Special color spaces
+--------------------
+
+The JPEG standard itself is "color blind" and doesn't specify any particular
+color space.  It is customary to convert color data to a luminance/chrominance
+color space before compressing, since this permits greater compression.  The
+existing de-facto JPEG file format standards specify YCbCr or grayscale data
+(JFIF), or grayscale, RGB, YCbCr, CMYK, or YCCK (Adobe).  For special
+applications such as multispectral images, other color spaces can be used,
+but it must be understood that such files will be unportable.
+
+The JPEG library can handle the most common colorspace conversions (namely
+RGB <=> YCbCr and CMYK <=> YCCK).  It can also deal with data of an unknown
+color space, passing it through without conversion.  If you deal extensively
+with an unusual color space, you can easily extend the library to understand
+additional color spaces and perform appropriate conversions.
+
+For compression, the source data's color space is specified by field
+in_color_space.  This is transformed to the JPEG file's color space given
+by jpeg_color_space.  jpeg_set_defaults() chooses a reasonable JPEG color
+space depending on in_color_space, but you can override this by calling
+jpeg_set_colorspace().  Of course you must select a supported transformation.
+jccolor.c currently supports the following transformations:
+	RGB => YCbCr
+	RGB => GRAYSCALE
+	YCbCr => GRAYSCALE
+	CMYK => YCCK
+plus the null transforms: GRAYSCALE => GRAYSCALE, RGB => RGB,
+YCbCr => YCbCr, CMYK => CMYK, YCCK => YCCK, and UNKNOWN => UNKNOWN.
+
+The de-facto file format standards (JFIF and Adobe) specify APPn markers that
+indicate the color space of the JPEG file.  It is important to ensure that
+these are written correctly, or omitted if the JPEG file's color space is not
+one of the ones supported by the de-facto standards.  jpeg_set_colorspace()
+will set the compression parameters to include or omit the APPn markers
+properly, so long as it is told the truth about the JPEG color space.
+For example, if you are writing some random 3-component color space without
+conversion, don't try to fake out the library by setting in_color_space and
+jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN.  You may want to write an
+APPn marker of your own devising to identify the colorspace --- see "Special
+markers", below.
+
+When told that the color space is UNKNOWN, the library will default to using
+luminance-quality compression parameters for all color components.  You may
+well want to change these parameters.  See the source code for
+jpeg_set_colorspace(), in jcparam.c, for details.
+
+For decompression, the JPEG file's color space is given in jpeg_color_space,
+and this is transformed to the output color space out_color_space.
+jpeg_read_header's setting of jpeg_color_space can be relied on if the file
+conforms to JFIF or Adobe conventions, but otherwise it is no better than a
+guess.  If you know the JPEG file's color space for certain, you can override
+jpeg_read_header's guess by setting jpeg_color_space.  jpeg_read_header also
+selects a default output color space based on (its guess of) jpeg_color_space;
+set out_color_space to override this.  Again, you must select a supported
+transformation.  jdcolor.c currently supports
+	YCbCr => GRAYSCALE
+	YCbCr => RGB
+	GRAYSCALE => RGB
+	YCCK => CMYK
+as well as the null transforms.  (Since GRAYSCALE=>RGB is provided, an
+application can force grayscale JPEGs to look like color JPEGs if it only
+wants to handle one case.)
+
+The two-pass color quantizer, jquant2.c, is specialized to handle RGB data
+(it weights distances appropriately for RGB colors).  You'll need to modify
+the code if you want to use it for non-RGB output color spaces.  Note that
+jquant2.c is used to map to an application-supplied colormap as well as for
+the normal two-pass colormap selection process.
+
+CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK JPEG
+files: 0 represents 100% ink coverage, rather than 0% ink as you'd expect.
+This is arguably a bug in Photoshop, but if you need to work with Photoshop
+CMYK files, you will have to deal with it in your application.  We cannot
+"fix" this in the library by inverting the data during the CMYK<=>YCCK
+transform, because that would break other applications, notably Ghostscript.
+Photoshop versions prior to 3.0 write EPS files containing JPEG-encoded CMYK
+data in the same inverted-YCCK representation used in bare JPEG files, but
+the surrounding PostScript code performs an inversion using the PS image
+operator.  I am told that Photoshop 3.0 will write uninverted YCCK in
+EPS/JPEG files, and will omit the PS-level inversion.  (But the data
+polarity used in bare JPEG files will not change in 3.0.)  In either case,
+the JPEG library must not invert the data itself, or else Ghostscript would
+read these EPS files incorrectly.
+
+
+Error handling
+--------------
+
+When the default error handler is used, any error detected inside the JPEG
+routines will cause a message to be printed on stderr, followed by exit().
+You can supply your own error handling routines to override this behavior
+and to control the treatment of nonfatal warnings and trace/debug messages.
+The file example.c illustrates the most common case, which is to have the
+application regain control after an error rather than exiting.
+
+The JPEG library never writes any message directly; it always goes through
+the error handling routines.  Three classes of messages are recognized:
+  * Fatal errors: the library cannot continue.
+  * Warnings: the library can continue, but the data is corrupt, and a
+    damaged output image is likely to result.
+  * Trace/informational messages.  These come with a trace level indicating
+    the importance of the message; you can control the verbosity of the
+    program by adjusting the maximum trace level that will be displayed.
+
+You may, if you wish, simply replace the entire JPEG error handling module
+(jerror.c) with your own code.  However, you can avoid code duplication by
+only replacing some of the routines depending on the behavior you need.
+This is accomplished by calling jpeg_std_error() as usual, but then overriding
+some of the method pointers in the jpeg_error_mgr struct, as illustrated by
+example.c.
+
+All of the error handling routines will receive a pointer to the JPEG object
+(a j_common_ptr which points to either a jpeg_compress_struct or a
+jpeg_decompress_struct; if you need to tell which, test the is_decompressor
+field).  This struct includes a pointer to the error manager struct in its
+"err" field.  Frequently, custom error handler routines will need to access
+additional data which is not known to the JPEG library or the standard error
+handler.  The most convenient way to do this is to embed either the JPEG
+object or the jpeg_error_mgr struct in a larger structure that contains
+additional fields; then casting the passed pointer provides access to the
+additional fields.  Again, see example.c for one way to do it.  (Beginning
+with IJG version 6b, there is also a void pointer "client_data" in each
+JPEG object, which the application can also use to find related data.
+The library does not touch client_data at all.)
+
+The individual methods that you might wish to override are:
+
+error_exit (j_common_ptr cinfo)
+	Receives control for a fatal error.  Information sufficient to
+	generate the error message has been stored in cinfo->err; call
+	output_message to display it.  Control must NOT return to the caller;
+	generally this routine will exit() or longjmp() somewhere.
+	Typically you would override this routine to get rid of the exit()
+	default behavior.  Note that if you continue processing, you should
+	clean up the JPEG object with jpeg_abort() or jpeg_destroy().
+
+output_message (j_common_ptr cinfo)
+	Actual output of any JPEG message.  Override this to send messages
+	somewhere other than stderr.  Note that this method does not know
+	how to generate a message, only where to send it.
+
+format_message (j_common_ptr cinfo, char * buffer)
+	Constructs a readable error message string based on the error info
+	stored in cinfo->err.  This method is called by output_message.  Few
+	applications should need to override this method.  One possible
+	reason for doing so is to implement dynamic switching of error message
+	language.
+
+emit_message (j_common_ptr cinfo, int msg_level)
+	Decide whether or not to emit a warning or trace message; if so,
+	calls output_message.  The main reason for overriding this method
+	would be to abort on warnings.  msg_level is -1 for warnings,
+	0 and up for trace messages.
+
+Only error_exit() and emit_message() are called from the rest of the JPEG
+library; the other two are internal to the error handler.
+
+The actual message texts are stored in an array of strings which is pointed to
+by the field err->jpeg_message_table.  The messages are numbered from 0 to
+err->last_jpeg_message, and it is these code numbers that are used in the
+JPEG library code.  You could replace the message texts (for instance, with
+messages in French or German) by changing the message table pointer.  See
+jerror.h for the default texts.  CAUTION: this table will almost certainly
+change or grow from one library version to the next.
+
+It may be useful for an application to add its own message texts that are
+handled by the same mechanism.  The error handler supports a second "add-on"
+message table for this purpose.  To define an addon table, set the pointer
+err->addon_message_table and the message numbers err->first_addon_message and
+err->last_addon_message.  If you number the addon messages beginning at 1000
+or so, you won't have to worry about conflicts with the library's built-in
+messages.  See the sample applications cjpeg/djpeg for an example of using
+addon messages (the addon messages are defined in cderror.h).
+
+Actual invocation of the error handler is done via macros defined in jerror.h:
+	ERREXITn(...)	for fatal errors
+	WARNMSn(...)	for corrupt-data warnings
+	TRACEMSn(...)	for trace and informational messages.
+These macros store the message code and any additional parameters into the
+error handler struct, then invoke the error_exit() or emit_message() method.
+The variants of each macro are for varying numbers of additional parameters.
+The additional parameters are inserted into the generated message using
+standard printf() format codes.
+
+See jerror.h and jerror.c for further details.
+
+
+Compressed data handling (source and destination managers)
+----------------------------------------------------------
+
+The JPEG compression library sends its compressed data to a "destination
+manager" module.  The default destination manager just writes the data to a
+stdio stream, but you can provide your own manager to do something else.
+Similarly, the decompression library calls a "source manager" to obtain the
+compressed data; you can provide your own source manager if you want the data
+to come from somewhere other than a stdio stream.
+
+In both cases, compressed data is processed a bufferload at a time: the
+destination or source manager provides a work buffer, and the library invokes
+the manager only when the buffer is filled or emptied.  (You could define a
+one-character buffer to force the manager to be invoked for each byte, but
+that would be rather inefficient.)  The buffer's size and location are
+controlled by the manager, not by the library.  For example, if you desired to
+decompress a JPEG datastream that was all in memory, you could just make the
+buffer pointer and length point to the original data in memory.  Then the
+buffer-reload procedure would be invoked only if the decompressor ran off the
+end of the datastream, which would indicate an erroneous datastream.
+
+The work buffer is defined as an array of datatype JOCTET, which is generally
+"char" or "unsigned char".  On a machine where char is not exactly 8 bits
+wide, you must define JOCTET as a wider data type and then modify the data
+source and destination modules to transcribe the work arrays into 8-bit units
+on external storage.
+
+A data destination manager struct contains a pointer and count defining the
+next byte to write in the work buffer and the remaining free space:
+
+	JOCTET * next_output_byte;  /* => next byte to write in buffer */
+	size_t free_in_buffer;      /* # of byte spaces remaining in buffer */
+
+The library increments the pointer and decrements the count until the buffer
+is filled.  The manager's empty_output_buffer method must reset the pointer
+and count.  The manager is expected to remember the buffer's starting address
+and total size in private fields not visible to the library.
+
+A data destination manager provides three methods:
+
+init_destination (j_compress_ptr cinfo)
+	Initialize destination.  This is called by jpeg_start_compress()
+	before any data is actually written.  It must initialize
+	next_output_byte and free_in_buffer.  free_in_buffer must be
+	initialized to a positive value.
+
+empty_output_buffer (j_compress_ptr cinfo)
+	This is called whenever the buffer has filled (free_in_buffer
+	reaches zero).  In typical applications, it should write out the
+	*entire* buffer (use the saved start address and buffer length;
+	ignore the current state of next_output_byte and free_in_buffer).
+	Then reset the pointer & count to the start of the buffer, and
+	return TRUE indicating that the buffer has been dumped.
+	free_in_buffer must be set to a positive value when TRUE is
+	returned.  A FALSE return should only be used when I/O suspension is
+	desired (this operating mode is discussed in the next section).
+
+term_destination (j_compress_ptr cinfo)
+	Terminate destination --- called by jpeg_finish_compress() after all
+	data has been written.  In most applications, this must flush any
+	data remaining in the buffer.  Use either next_output_byte or
+	free_in_buffer to determine how much data is in the buffer.
+
+term_destination() is NOT called by jpeg_abort() or jpeg_destroy().  If you
+want the destination manager to be cleaned up during an abort, you must do it
+yourself.
+
+You will also need code to create a jpeg_destination_mgr struct, fill in its
+method pointers, and insert a pointer to the struct into the "dest" field of
+the JPEG compression object.  This can be done in-line in your setup code if
+you like, but it's probably cleaner to provide a separate routine similar to
+the jpeg_stdio_dest() routine of the supplied destination manager.
+
+Decompression source managers follow a parallel design, but with some
+additional frammishes.  The source manager struct contains a pointer and count
+defining the next byte to read from the work buffer and the number of bytes
+remaining:
+
+	const JOCTET * next_input_byte; /* => next byte to read from buffer */
+	size_t bytes_in_buffer;         /* # of bytes remaining in buffer */
+
+The library increments the pointer and decrements the count until the buffer
+is emptied.  The manager's fill_input_buffer method must reset the pointer and
+count.  In most applications, the manager must remember the buffer's starting
+address and total size in private fields not visible to the library.
+
+A data source manager provides five methods:
+
+init_source (j_decompress_ptr cinfo)
+	Initialize source.  This is called by jpeg_read_header() before any
+	data is actually read.  Unlike init_destination(), it may leave
+	bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
+	will occur immediately).
+
+fill_input_buffer (j_decompress_ptr cinfo)
+	This is called whenever bytes_in_buffer has reached zero and more
+	data is wanted.  In typical applications, it should read fresh data
+	into the buffer (ignoring the current state of next_input_byte and
+	bytes_in_buffer), reset the pointer & count to the start of the
+	buffer, and return TRUE indicating that the buffer has been reloaded.
+	It is not necessary to fill the buffer entirely, only to obtain at
+	least one more byte.  bytes_in_buffer MUST be set to a positive value
+	if TRUE is returned.  A FALSE return should only be used when I/O
+	suspension is desired (this mode is discussed in the next section).
+
+skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+	Skip num_bytes worth of data.  The buffer pointer and count should
+	be advanced over num_bytes input bytes, refilling the buffer as
+	needed.  This is used to skip over a potentially large amount of
+	uninteresting data (such as an APPn marker).  In some applications
+	it may be possible to optimize away the reading of the skipped data,
+	but it's not clear that being smart is worth much trouble; large
+	skips are uncommon.  bytes_in_buffer may be zero on return.
+	A zero or negative skip count should be treated as a no-op.
+
+resync_to_restart (j_decompress_ptr cinfo, int desired)
+	This routine is called only when the decompressor has failed to find
+	a restart (RSTn) marker where one is expected.  Its mission is to
+	find a suitable point for resuming decompression.  For most
+	applications, we recommend that you just use the default resync
+	procedure, jpeg_resync_to_restart().  However, if you are able to back
+	up in the input data stream, or if you have a-priori knowledge about
+	the likely location of restart markers, you may be able to do better.
+	Read the read_restart_marker() and jpeg_resync_to_restart() routines
+	in jdmarker.c if you think you'd like to implement your own resync
+	procedure.
+
+term_source (j_decompress_ptr cinfo)
+	Terminate source --- called by jpeg_finish_decompress() after all
+	data has been read.  Often a no-op.
+
+For both fill_input_buffer() and skip_input_data(), there is no such thing
+as an EOF return.  If the end of the file has been reached, the routine has
+a choice of exiting via ERREXIT() or inserting fake data into the buffer.
+In most cases, generating a warning message and inserting a fake EOI marker
+is the best course of action --- this will allow the decompressor to output
+however much of the image is there.  In pathological cases, the decompressor
+may swallow the EOI and again demand data ... just keep feeding it fake EOIs.
+jdatasrc.c illustrates the recommended error recovery behavior.
+
+term_source() is NOT called by jpeg_abort() or jpeg_destroy().  If you want
+the source manager to be cleaned up during an abort, you must do it yourself.
+
+You will also need code to create a jpeg_source_mgr struct, fill in its method
+pointers, and insert a pointer to the struct into the "src" field of the JPEG
+decompression object.  This can be done in-line in your setup code if you
+like, but it's probably cleaner to provide a separate routine similar to the
+jpeg_stdio_src() routine of the supplied source manager.
+
+For more information, consult the stdio source and destination managers
+in jdatasrc.c and jdatadst.c.
+
+
+I/O suspension
+--------------
+
+Some applications need to use the JPEG library as an incremental memory-to-
+memory filter: when the compressed data buffer is filled or emptied, they want
+control to return to the outer loop, rather than expecting that the buffer can
+be emptied or reloaded within the data source/destination manager subroutine.
+The library supports this need by providing an "I/O suspension" mode, which we
+describe in this section.
+
+The I/O suspension mode is not a panacea: nothing is guaranteed about the
+maximum amount of time spent in any one call to the library, so it will not
+eliminate response-time problems in single-threaded applications.  If you
+need guaranteed response time, we suggest you "bite the bullet" and implement
+a real multi-tasking capability.
+
+To use I/O suspension, cooperation is needed between the calling application
+and the data source or destination manager; you will always need a custom
+source/destination manager.  (Please read the previous section if you haven't
+already.)  The basic idea is that the empty_output_buffer() or
+fill_input_buffer() routine is a no-op, merely returning FALSE to indicate
+that it has done nothing.  Upon seeing this, the JPEG library suspends
+operation and returns to its caller.  The surrounding application is
+responsible for emptying or refilling the work buffer before calling the
+JPEG library again.
+
+Compression suspension:
+
+For compression suspension, use an empty_output_buffer() routine that returns
+FALSE; typically it will not do anything else.  This will cause the
+compressor to return to the caller of jpeg_write_scanlines(), with the return
+value indicating that not all the supplied scanlines have been accepted.
+The application must make more room in the output buffer, adjust the output
+buffer pointer/count appropriately, and then call jpeg_write_scanlines()
+again, pointing to the first unconsumed scanline.
+
+When forced to suspend, the compressor will backtrack to a convenient stopping
+point (usually the start of the current MCU); it will regenerate some output
+data when restarted.  Therefore, although empty_output_buffer() is only
+called when the buffer is filled, you should NOT write out the entire buffer
+after a suspension.  Write only the data up to the current position of
+next_output_byte/free_in_buffer.  The data beyond that point will be
+regenerated after resumption.
+
+Because of the backtracking behavior, a good-size output buffer is essential
+for efficiency; you don't want the compressor to suspend often.  (In fact, an
+overly small buffer could lead to infinite looping, if a single MCU required
+more data than would fit in the buffer.)  We recommend a buffer of at least
+several Kbytes.  You may want to insert explicit code to ensure that you don't
+call jpeg_write_scanlines() unless there is a reasonable amount of space in
+the output buffer; in other words, flush the buffer before trying to compress
+more data.
+
+The compressor does not allow suspension while it is trying to write JPEG
+markers at the beginning and end of the file.  This means that:
+  * At the beginning of a compression operation, there must be enough free
+    space in the output buffer to hold the header markers (typically 600 or
+    so bytes).  The recommended buffer size is bigger than this anyway, so
+    this is not a problem as long as you start with an empty buffer.  However,
+    this restriction might catch you if you insert large special markers, such
+    as a JFIF thumbnail image, without flushing the buffer afterwards.
+  * When you call jpeg_finish_compress(), there must be enough space in the
+    output buffer to emit any buffered data and the final EOI marker.  In the
+    current implementation, half a dozen bytes should suffice for this, but
+    for safety's sake we recommend ensuring that at least 100 bytes are free
+    before calling jpeg_finish_compress().
+
+A more significant restriction is that jpeg_finish_compress() cannot suspend.
+This means you cannot use suspension with multi-pass operating modes, namely
+Huffman code optimization and multiple-scan output.  Those modes write the
+whole file during jpeg_finish_compress(), which will certainly result in
+buffer overrun.  (Note that this restriction applies only to compression,
+not decompression.  The decompressor supports input suspension in all of its
+operating modes.)
+
+Decompression suspension:
+
+For decompression suspension, use a fill_input_buffer() routine that simply
+returns FALSE (except perhaps during error recovery, as discussed below).
+This will cause the decompressor to return to its caller with an indication
+that suspension has occurred.  This can happen at four places:
+  * jpeg_read_header(): will return JPEG_SUSPENDED.
+  * jpeg_start_decompress(): will return FALSE, rather than its usual TRUE.
+  * jpeg_read_scanlines(): will return the number of scanlines already
+	completed (possibly 0).
+  * jpeg_finish_decompress(): will return FALSE, rather than its usual TRUE.
+The surrounding application must recognize these cases, load more data into
+the input buffer, and repeat the call.  In the case of jpeg_read_scanlines(),
+increment the passed pointers past any scanlines successfully read.
+
+Just as with compression, the decompressor will typically backtrack to a
+convenient restart point before suspending.  When fill_input_buffer() is
+called, next_input_byte/bytes_in_buffer point to the current restart point,
+which is where the decompressor will backtrack to if FALSE is returned.
+The data beyond that position must NOT be discarded if you suspend; it needs
+to be re-read upon resumption.  In most implementations, you'll need to shift
+this data down to the start of your work buffer and then load more data after
+it.  Again, this behavior means that a several-Kbyte work buffer is essential
+for decent performance; furthermore, you should load a reasonable amount of
+new data before resuming decompression.  (If you loaded, say, only one new
+byte each time around, you could waste a LOT of cycles.)
+
+The skip_input_data() source manager routine requires special care in a
+suspension scenario.  This routine is NOT granted the ability to suspend the
+decompressor; it can decrement bytes_in_buffer to zero, but no more.  If the
+requested skip distance exceeds the amount of data currently in the input
+buffer, then skip_input_data() must set bytes_in_buffer to zero and record the
+additional skip distance somewhere else.  The decompressor will immediately
+call fill_input_buffer(), which should return FALSE, which will cause a
+suspension return.  The surrounding application must then arrange to discard
+the recorded number of bytes before it resumes loading the input buffer.
+(Yes, this design is rather baroque, but it avoids complexity in the far more
+common case where a non-suspending source manager is used.)
+
+If the input data has been exhausted, we recommend that you emit a warning
+and insert dummy EOI markers just as a non-suspending data source manager
+would do.  This can be handled either in the surrounding application logic or
+within fill_input_buffer(); the latter is probably more efficient.  If
+fill_input_buffer() knows that no more data is available, it can set the
+pointer/count to point to a dummy EOI marker and then return TRUE just as
+though it had read more data in a non-suspending situation.
+
+The decompressor does not attempt to suspend within standard JPEG markers;
+instead it will backtrack to the start of the marker and reprocess the whole
+marker next time.  Hence the input buffer must be large enough to hold the
+longest standard marker in the file.  Standard JPEG markers should normally
+not exceed a few hundred bytes each (DHT tables are typically the longest).
+We recommend at least a 2K buffer for performance reasons, which is much
+larger than any correct marker is likely to be.  For robustness against
+damaged marker length counts, you may wish to insert a test in your
+application for the case that the input buffer is completely full and yet
+the decoder has suspended without consuming any data --- otherwise, if this
+situation did occur, it would lead to an endless loop.  (The library can't
+provide this test since it has no idea whether "the buffer is full", or
+even whether there is a fixed-size input buffer.)
+
+The input buffer would need to be 64K to allow for arbitrary COM or APPn
+markers, but these are handled specially: they are either saved into allocated
+memory, or skipped over by calling skip_input_data().  In the former case,
+suspension is handled correctly, and in the latter case, the problem of
+buffer overrun is placed on skip_input_data's shoulders, as explained above.
+Note that if you provide your own marker handling routine for large markers,
+you should consider how to deal with buffer overflow.
+
+Multiple-buffer management:
+
+In some applications it is desirable to store the compressed data in a linked
+list of buffer areas, so as to avoid data copying.  This can be handled by
+having empty_output_buffer() or fill_input_buffer() set the pointer and count
+to reference the next available buffer; FALSE is returned only if no more
+buffers are available.  Although seemingly straightforward, there is a
+pitfall in this approach: the backtrack that occurs when FALSE is returned
+could back up into an earlier buffer.  For example, when fill_input_buffer()
+is called, the current pointer & count indicate the backtrack restart point.
+Since fill_input_buffer() will set the pointer and count to refer to a new
+buffer, the restart position must be saved somewhere else.  Suppose a second
+call to fill_input_buffer() occurs in the same library call, and no
+additional input data is available, so fill_input_buffer must return FALSE.
+If the JPEG library has not moved the pointer/count forward in the current
+buffer, then *the correct restart point is the saved position in the prior
+buffer*.  Prior buffers may be discarded only after the library establishes
+a restart point within a later buffer.  Similar remarks apply for output into
+a chain of buffers.
+
+The library will never attempt to backtrack over a skip_input_data() call,
+so any skipped data can be permanently discarded.  You still have to deal
+with the case of skipping not-yet-received data, however.
+
+It's much simpler to use only a single buffer; when fill_input_buffer() is
+called, move any unconsumed data (beyond the current pointer/count) down to
+the beginning of this buffer and then load new data into the remaining buffer
+space.  This approach requires a little more data copying but is far easier
+to get right.
+
+
+Progressive JPEG support
+------------------------
+
+Progressive JPEG rearranges the stored data into a series of scans of
+increasing quality.  In situations where a JPEG file is transmitted across a
+slow communications link, a decoder can generate a low-quality image very
+quickly from the first scan, then gradually improve the displayed quality as
+more scans are received.  The final image after all scans are complete is
+identical to that of a regular (sequential) JPEG file of the same quality
+setting.  Progressive JPEG files are often slightly smaller than equivalent
+sequential JPEG files, but the possibility of incremental display is the main
+reason for using progressive JPEG.
+
+The IJG encoder library generates progressive JPEG files when given a
+suitable "scan script" defining how to divide the data into scans.
+Creation of progressive JPEG files is otherwise transparent to the encoder.
+Progressive JPEG files can also be read transparently by the decoder library.
+If the decoding application simply uses the library as defined above, it
+will receive a final decoded image without any indication that the file was
+progressive.  Of course, this approach does not allow incremental display.
+To perform incremental display, an application needs to use the decoder
+library's "buffered-image" mode, in which it receives a decoded image
+multiple times.
+
+Each displayed scan requires about as much work to decode as a full JPEG
+image of the same size, so the decoder must be fairly fast in relation to the
+data transmission rate in order to make incremental display useful.  However,
+it is possible to skip displaying the image and simply add the incoming bits
+to the decoder's coefficient buffer.  This is fast because only Huffman
+decoding need be done, not IDCT, upsampling, colorspace conversion, etc.
+The IJG decoder library allows the application to switch dynamically between
+displaying the image and simply absorbing the incoming bits.  A properly
+coded application can automatically adapt the number of display passes to
+suit the time available as the image is received.  Also, a final
+higher-quality display cycle can be performed from the buffered data after
+the end of the file is reached.
+
+Progressive compression:
+
+To create a progressive JPEG file (or a multiple-scan sequential JPEG file),
+set the scan_info cinfo field to point to an array of scan descriptors, and
+perform compression as usual.  Instead of constructing your own scan list,
+you can call the jpeg_simple_progression() helper routine to create a
+recommended progression sequence; this method should be used by all
+applications that don't want to get involved in the nitty-gritty of
+progressive scan sequence design.  (If you want to provide user control of
+scan sequences, you may wish to borrow the scan script reading code found
+in rdswitch.c, so that you can read scan script files just like cjpeg's.)
+When scan_info is not NULL, the compression library will store DCT'd data
+into a buffer array as jpeg_write_scanlines() is called, and will emit all
+the requested scans during jpeg_finish_compress().  This implies that
+multiple-scan output cannot be created with a suspending data destination
+manager, since jpeg_finish_compress() does not support suspension.  We
+should also note that the compressor currently forces Huffman optimization
+mode when creating a progressive JPEG file, because the default Huffman
+tables are unsuitable for progressive files.
+
+Progressive decompression:
+
+When buffered-image mode is not used, the decoder library will read all of
+a multi-scan file during jpeg_start_decompress(), so that it can provide a
+final decoded image.  (Here "multi-scan" means either progressive or
+multi-scan sequential.)  This makes multi-scan files transparent to the
+decoding application.  However, existing applications that used suspending
+input with version 5 of the IJG library will need to be modified to check
+for a suspension return from jpeg_start_decompress().
+
+To perform incremental display, an application must use the library's
+buffered-image mode.  This is described in the next section.
+
+
+Buffered-image mode
+-------------------
+
+In buffered-image mode, the library stores the partially decoded image in a
+coefficient buffer, from which it can be read out as many times as desired.
+This mode is typically used for incremental display of progressive JPEG files,
+but it can be used with any JPEG file.  Each scan of a progressive JPEG file
+adds more data (more detail) to the buffered image.  The application can
+display in lockstep with the source file (one display pass per input scan),
+or it can allow input processing to outrun display processing.  By making
+input and display processing run independently, it is possible for the
+application to adapt progressive display to a wide range of data transmission
+rates.
+
+The basic control flow for buffered-image decoding is
+
+	jpeg_create_decompress()
+	set data source
+	jpeg_read_header()
+	set overall decompression parameters
+	cinfo.buffered_image = TRUE;	/* select buffered-image mode */
+	jpeg_start_decompress()
+	for (each output pass) {
+	    adjust output decompression parameters if required
+	    jpeg_start_output()		/* start a new output pass */
+	    for (all scanlines in image) {
+	        jpeg_read_scanlines()
+	        display scanlines
+	    }
+	    jpeg_finish_output()	/* terminate output pass */
+	}
+	jpeg_finish_decompress()
+	jpeg_destroy_decompress()
+
+This differs from ordinary unbuffered decoding in that there is an additional
+level of looping.  The application can choose how many output passes to make
+and how to display each pass.
+
+The simplest approach to displaying progressive images is to do one display
+pass for each scan appearing in the input file.  In this case the outer loop
+condition is typically
+	while (! jpeg_input_complete(&cinfo))
+and the start-output call should read
+	jpeg_start_output(&cinfo, cinfo.input_scan_number);
+The second parameter to jpeg_start_output() indicates which scan of the input
+file is to be displayed; the scans are numbered starting at 1 for this
+purpose.  (You can use a loop counter starting at 1 if you like, but using
+the library's input scan counter is easier.)  The library automatically reads
+data as necessary to complete each requested scan, and jpeg_finish_output()
+advances to the next scan or end-of-image marker (hence input_scan_number
+will be incremented by the time control arrives back at jpeg_start_output()).
+With this technique, data is read from the input file only as needed, and
+input and output processing run in lockstep.
+
+After reading the final scan and reaching the end of the input file, the
+buffered image remains available; it can be read additional times by
+repeating the jpeg_start_output()/jpeg_read_scanlines()/jpeg_finish_output()
+sequence.  For example, a useful technique is to use fast one-pass color
+quantization for display passes made while the image is arriving, followed by
+a final display pass using two-pass quantization for highest quality.  This
+is done by changing the library parameters before the final output pass.
+Changing parameters between passes is discussed in detail below.
+
+In general the last scan of a progressive file cannot be recognized as such
+until after it is read, so a post-input display pass is the best approach if
+you want special processing in the final pass.
+
+When done with the image, be sure to call jpeg_finish_decompress() to release
+the buffered image (or just use jpeg_destroy_decompress()).
+
+If input data arrives faster than it can be displayed, the application can
+cause the library to decode input data in advance of what's needed to produce
+output.  This is done by calling the routine jpeg_consume_input().
+The return value is one of the following:
+	JPEG_REACHED_SOS:    reached an SOS marker (the start of a new scan)
+	JPEG_REACHED_EOI:    reached the EOI marker (end of image)
+	JPEG_ROW_COMPLETED:  completed reading one MCU row of compressed data
+	JPEG_SCAN_COMPLETED: completed reading last MCU row of current scan
+	JPEG_SUSPENDED:      suspended before completing any of the above
+(JPEG_SUSPENDED can occur only if a suspending data source is used.)  This
+routine can be called at any time after initializing the JPEG object.  It
+reads some additional data and returns when one of the indicated significant
+events occurs.  (If called after the EOI marker is reached, it will
+immediately return JPEG_REACHED_EOI without attempting to read more data.)
+
+The library's output processing will automatically call jpeg_consume_input()
+whenever the output processing overtakes the input; thus, simple lockstep
+display requires no direct calls to jpeg_consume_input().  But by adding
+calls to jpeg_consume_input(), you can absorb data in advance of what is
+being displayed.  This has two benefits:
+  * You can limit buildup of unprocessed data in your input buffer.
+  * You can eliminate extra display passes by paying attention to the
+    state of the library's input processing.
+
+The first of these benefits only requires interspersing calls to
+jpeg_consume_input() with your display operations and any other processing
+you may be doing.  To avoid wasting cycles due to backtracking, it's best to
+call jpeg_consume_input() only after a hundred or so new bytes have arrived.
+This is discussed further under "I/O suspension", above.  (Note: the JPEG
+library currently is not thread-safe.  You must not call jpeg_consume_input()
+from one thread of control if a different library routine is working on the
+same JPEG object in another thread.)
+
+When input arrives fast enough that more than one new scan is available
+before you start a new output pass, you may as well skip the output pass
+corresponding to the completed scan.  This occurs for free if you pass
+cinfo.input_scan_number as the target scan number to jpeg_start_output().
+The input_scan_number field is simply the index of the scan currently being
+consumed by the input processor.  You can ensure that this is up-to-date by
+emptying the input buffer just before calling jpeg_start_output(): call
+jpeg_consume_input() repeatedly until it returns JPEG_SUSPENDED or
+JPEG_REACHED_EOI.
+
+The target scan number passed to jpeg_start_output() is saved in the
+cinfo.output_scan_number field.  The library's output processing calls
+jpeg_consume_input() whenever the current input scan number and row within
+that scan is less than or equal to the current output scan number and row.
+Thus, input processing can "get ahead" of the output processing but is not
+allowed to "fall behind".  You can achieve several different effects by
+manipulating this interlock rule.  For example, if you pass a target scan
+number greater than the current input scan number, the output processor will
+wait until that scan starts to arrive before producing any output.  (To avoid
+an infinite loop, the target scan number is automatically reset to the last
+scan number when the end of image is reached.  Thus, if you specify a large
+target scan number, the library will just absorb the entire input file and
+then perform an output pass.  This is effectively the same as what
+jpeg_start_decompress() does when you don't select buffered-image mode.)
+When you pass a target scan number equal to the current input scan number,
+the image is displayed no faster than the current input scan arrives.  The
+final possibility is to pass a target scan number less than the current input
+scan number; this disables the input/output interlock and causes the output
+processor to simply display whatever it finds in the image buffer, without
+waiting for input.  (However, the library will not accept a target scan
+number less than one, so you can't avoid waiting for the first scan.)
+
+When data is arriving faster than the output display processing can advance
+through the image, jpeg_consume_input() will store data into the buffered
+image beyond the point at which the output processing is reading data out
+again.  If the input arrives fast enough, it may "wrap around" the buffer to
+the point where the input is more than one whole scan ahead of the output.
+If the output processing simply proceeds through its display pass without
+paying attention to the input, the effect seen on-screen is that the lower
+part of the image is one or more scans better in quality than the upper part.
+Then, when the next output scan is started, you have a choice of what target
+scan number to use.  The recommended choice is to use the current input scan
+number at that time, which implies that you've skipped the output scans
+corresponding to the input scans that were completed while you processed the
+previous output scan.  In this way, the decoder automatically adapts its
+speed to the arriving data, by skipping output scans as necessary to keep up
+with the arriving data.
+
+When using this strategy, you'll want to be sure that you perform a final
+output pass after receiving all the data; otherwise your last display may not
+be full quality across the whole screen.  So the right outer loop logic is
+something like this:
+	do {
+	    absorb any waiting input by calling jpeg_consume_input()
+	    final_pass = jpeg_input_complete(&cinfo);
+	    adjust output decompression parameters if required
+	    jpeg_start_output(&cinfo, cinfo.input_scan_number);
+	    ...
+	    jpeg_finish_output()
+	} while (! final_pass);
+rather than quitting as soon as jpeg_input_complete() returns TRUE.  This
+arrangement makes it simple to use higher-quality decoding parameters
+for the final pass.  But if you don't want to use special parameters for
+the final pass, the right loop logic is like this:
+	for (;;) {
+	    absorb any waiting input by calling jpeg_consume_input()
+	    jpeg_start_output(&cinfo, cinfo.input_scan_number);
+	    ...
+	    jpeg_finish_output()
+	    if (jpeg_input_complete(&cinfo) &&
+	        cinfo.input_scan_number == cinfo.output_scan_number)
+	      break;
+	}
+In this case you don't need to know in advance whether an output pass is to
+be the last one, so it's not necessary to have reached EOF before starting
+the final output pass; rather, what you want to test is whether the output
+pass was performed in sync with the final input scan.  This form of the loop
+will avoid an extra output pass whenever the decoder is able (or nearly able)
+to keep up with the incoming data.
+
+When the data transmission speed is high, you might begin a display pass,
+then find that much or all of the file has arrived before you can complete
+the pass.  (You can detect this by noting the JPEG_REACHED_EOI return code
+from jpeg_consume_input(), or equivalently by testing jpeg_input_complete().)
+In this situation you may wish to abort the current display pass and start a
+new one using the newly arrived information.  To do so, just call
+jpeg_finish_output() and then start a new pass with jpeg_start_output().
+
+A variant strategy is to abort and restart display if more than one complete
+scan arrives during an output pass; this can be detected by noting
+JPEG_REACHED_SOS returns and/or examining cinfo.input_scan_number.  This
+idea should be employed with caution, however, since the display process
+might never get to the bottom of the image before being aborted, resulting
+in the lower part of the screen being several passes worse than the upper.
+In most cases it's probably best to abort an output pass only if the whole
+file has arrived and you want to begin the final output pass immediately.
+
+When receiving data across a communication link, we recommend always using
+the current input scan number for the output target scan number; if a
+higher-quality final pass is to be done, it should be started (aborting any
+incomplete output pass) as soon as the end of file is received.  However,
+many other strategies are possible.  For example, the application can examine
+the parameters of the current input scan and decide whether to display it or
+not.  If the scan contains only chroma data, one might choose not to use it
+as the target scan, expecting that the scan will be small and will arrive
+quickly.  To skip to the next scan, call jpeg_consume_input() until it
+returns JPEG_REACHED_SOS or JPEG_REACHED_EOI.  Or just use the next higher
+number as the target scan for jpeg_start_output(); but that method doesn't
+let you inspect the next scan's parameters before deciding to display it.
+
+
+In buffered-image mode, jpeg_start_decompress() never performs input and
+thus never suspends.  An application that uses input suspension with
+buffered-image mode must be prepared for suspension returns from these
+routines:
+* jpeg_start_output() performs input only if you request 2-pass quantization
+  and the target scan isn't fully read yet.  (This is discussed below.)
+* jpeg_read_scanlines(), as always, returns the number of scanlines that it
+  was able to produce before suspending.
+* jpeg_finish_output() will read any markers following the target scan,
+  up to the end of the file or the SOS marker that begins another scan.
+  (But it reads no input if jpeg_consume_input() has already reached the
+  end of the file or a SOS marker beyond the target output scan.)
+* jpeg_finish_decompress() will read until the end of file, and thus can
+  suspend if the end hasn't already been reached (as can be tested by
+  calling jpeg_input_complete()).
+jpeg_start_output(), jpeg_finish_output(), and jpeg_finish_decompress()
+all return TRUE if they completed their tasks, FALSE if they had to suspend.
+In the event of a FALSE return, the application must load more input data
+and repeat the call.  Applications that use non-suspending data sources need
+not check the return values of these three routines.
+
+
+It is possible to change decoding parameters between output passes in the
+buffered-image mode.  The decoder library currently supports only very
+limited changes of parameters.  ONLY THE FOLLOWING parameter changes are
+allowed after jpeg_start_decompress() is called:
+* dct_method can be changed before each call to jpeg_start_output().
+  For example, one could use a fast DCT method for early scans, changing
+  to a higher quality method for the final scan.
+* dither_mode can be changed before each call to jpeg_start_output();
+  of course this has no impact if not using color quantization.  Typically
+  one would use ordered dither for initial passes, then switch to
+  Floyd-Steinberg dither for the final pass.  Caution: changing dither mode
+  can cause more memory to be allocated by the library.  Although the amount
+  of memory involved is not large (a scanline or so), it may cause the
+  initial max_memory_to_use specification to be exceeded, which in the worst
+  case would result in an out-of-memory failure.
+* do_block_smoothing can be changed before each call to jpeg_start_output().
+  This setting is relevant only when decoding a progressive JPEG image.
+  During the first DC-only scan, block smoothing provides a very "fuzzy" look
+  instead of the very "blocky" look seen without it; which is better seems a
+  matter of personal taste.  But block smoothing is nearly always a win
+  during later stages, especially when decoding a successive-approximation
+  image: smoothing helps to hide the slight blockiness that otherwise shows
+  up on smooth gradients until the lowest coefficient bits are sent.
+* Color quantization mode can be changed under the rules described below.
+  You *cannot* change between full-color and quantized output (because that
+  would alter the required I/O buffer sizes), but you can change which
+  quantization method is used.
+
+When generating color-quantized output, changing quantization method is a
+very useful way of switching between high-speed and high-quality display.
+The library allows you to change among its three quantization methods:
+1. Single-pass quantization to a fixed color cube.
+   Selected by cinfo.two_pass_quantize = FALSE and cinfo.colormap = NULL.
+2. Single-pass quantization to an application-supplied colormap.
+   Selected by setting cinfo.colormap to point to the colormap (the value of
+   two_pass_quantize is ignored); also set cinfo.actual_number_of_colors.
+3. Two-pass quantization to a colormap chosen specifically for the image.
+   Selected by cinfo.two_pass_quantize = TRUE and cinfo.colormap = NULL.
+   (This is the default setting selected by jpeg_read_header, but it is
+   probably NOT what you want for the first pass of progressive display!)
+These methods offer successively better quality and lesser speed.  However,
+only the first method is available for quantizing in non-RGB color spaces.
+
+IMPORTANT: because the different quantizer methods have very different
+working-storage requirements, the library requires you to indicate which
+one(s) you intend to use before you call jpeg_start_decompress().  (If we did
+not require this, the max_memory_to_use setting would be a complete fiction.)
+You do this by setting one or more of these three cinfo fields to TRUE:
+	enable_1pass_quant		Fixed color cube colormap
+	enable_external_quant		Externally-supplied colormap
+	enable_2pass_quant		Two-pass custom colormap
+All three are initialized FALSE by jpeg_read_header().  But
+jpeg_start_decompress() automatically sets TRUE the one selected by the
+current two_pass_quantize and colormap settings, so you only need to set the
+enable flags for any other quantization methods you plan to change to later.
+
+After setting the enable flags correctly at jpeg_start_decompress() time, you
+can change to any enabled quantization method by setting two_pass_quantize
+and colormap properly just before calling jpeg_start_output().  The following
+special rules apply:
+1. You must explicitly set cinfo.colormap to NULL when switching to 1-pass
+   or 2-pass mode from a different mode, or when you want the 2-pass
+   quantizer to be re-run to generate a new colormap.
+2. To switch to an external colormap, or to change to a different external
+   colormap than was used on the prior pass, you must call
+   jpeg_new_colormap() after setting cinfo.colormap.
+NOTE: if you want to use the same colormap as was used in the prior pass,
+you should not do either of these things.  This will save some nontrivial
+switchover costs.
+(These requirements exist because cinfo.colormap will always be non-NULL
+after completing a prior output pass, since both the 1-pass and 2-pass
+quantizers set it to point to their output colormaps.  Thus you have to
+do one of these two things to notify the library that something has changed.
+Yup, it's a bit klugy, but it's necessary to do it this way for backwards
+compatibility.)
+
+Note that in buffered-image mode, the library generates any requested colormap
+during jpeg_start_output(), not during jpeg_start_decompress().
+
+When using two-pass quantization, jpeg_start_output() makes a pass over the
+buffered image to determine the optimum color map; it therefore may take a
+significant amount of time, whereas ordinarily it does little work.  The
+progress monitor hook is called during this pass, if defined.  It is also
+important to realize that if the specified target scan number is greater than
+or equal to the current input scan number, jpeg_start_output() will attempt
+to consume input as it makes this pass.  If you use a suspending data source,
+you need to check for a FALSE return from jpeg_start_output() under these
+conditions.  The combination of 2-pass quantization and a not-yet-fully-read
+target scan is the only case in which jpeg_start_output() will consume input.
+
+
+Application authors who support buffered-image mode may be tempted to use it
+for all JPEG images, even single-scan ones.  This will work, but it is
+inefficient: there is no need to create an image-sized coefficient buffer for
+single-scan images.  Requesting buffered-image mode for such an image wastes
+memory.  Worse, it can cost time on large images, since the buffered data has
+to be swapped out or written to a temporary file.  If you are concerned about
+maximum performance on baseline JPEG files, you should use buffered-image
+mode only when the incoming file actually has multiple scans.  This can be
+tested by calling jpeg_has_multiple_scans(), which will return a correct
+result at any time after jpeg_read_header() completes.
+
+It is also worth noting that when you use jpeg_consume_input() to let input
+processing get ahead of output processing, the resulting pattern of access to
+the coefficient buffer is quite nonsequential.  It's best to use the memory
+manager jmemnobs.c if you can (ie, if you have enough real or virtual main
+memory).  If not, at least make sure that max_memory_to_use is set as high as
+possible.  If the JPEG memory manager has to use a temporary file, you will
+probably see a lot of disk traffic and poor performance.  (This could be
+improved with additional work on the memory manager, but we haven't gotten
+around to it yet.)
+
+In some applications it may be convenient to use jpeg_consume_input() for all
+input processing, including reading the initial markers; that is, you may
+wish to call jpeg_consume_input() instead of jpeg_read_header() during
+startup.  This works, but note that you must check for JPEG_REACHED_SOS and
+JPEG_REACHED_EOI return codes as the equivalent of jpeg_read_header's codes.
+Once the first SOS marker has been reached, you must call
+jpeg_start_decompress() before jpeg_consume_input() will consume more input;
+it'll just keep returning JPEG_REACHED_SOS until you do.  If you read a
+tables-only file this way, jpeg_consume_input() will return JPEG_REACHED_EOI
+without ever returning JPEG_REACHED_SOS; be sure to check for this case.
+If this happens, the decompressor will not read any more input until you call
+jpeg_abort() to reset it.  It is OK to call jpeg_consume_input() even when not
+using buffered-image mode, but in that case it's basically a no-op after the
+initial markers have been read: it will just return JPEG_SUSPENDED.
+
+
+Abbreviated datastreams and multiple images
+-------------------------------------------
+
+A JPEG compression or decompression object can be reused to process multiple
+images.  This saves a small amount of time per image by eliminating the
+"create" and "destroy" operations, but that isn't the real purpose of the
+feature.  Rather, reuse of an object provides support for abbreviated JPEG
+datastreams.  Object reuse can also simplify processing a series of images in
+a single input or output file.  This section explains these features.
+
+A JPEG file normally contains several hundred bytes worth of quantization
+and Huffman tables.  In a situation where many images will be stored or
+transmitted with identical tables, this may represent an annoying overhead.
+The JPEG standard therefore permits tables to be omitted.  The standard
+defines three classes of JPEG datastreams:
+  * "Interchange" datastreams contain an image and all tables needed to decode
+     the image.  These are the usual kind of JPEG file.
+  * "Abbreviated image" datastreams contain an image, but are missing some or
+    all of the tables needed to decode that image.
+  * "Abbreviated table specification" (henceforth "tables-only") datastreams
+    contain only table specifications.
+To decode an abbreviated image, it is necessary to load the missing table(s)
+into the decoder beforehand.  This can be accomplished by reading a separate
+tables-only file.  A variant scheme uses a series of images in which the first
+image is an interchange (complete) datastream, while subsequent ones are
+abbreviated and rely on the tables loaded by the first image.  It is assumed
+that once the decoder has read a table, it will remember that table until a
+new definition for the same table number is encountered.
+
+It is the application designer's responsibility to figure out how to associate
+the correct tables with an abbreviated image.  While abbreviated datastreams
+can be useful in a closed environment, their use is strongly discouraged in
+any situation where data exchange with other applications might be needed.
+Caveat designer.
+
+The JPEG library provides support for reading and writing any combination of
+tables-only datastreams and abbreviated images.  In both compression and
+decompression objects, a quantization or Huffman table will be retained for
+the lifetime of the object, unless it is overwritten by a new table definition.
+
+
+To create abbreviated image datastreams, it is only necessary to tell the
+compressor not to emit some or all of the tables it is using.  Each
+quantization and Huffman table struct contains a boolean field "sent_table",
+which normally is initialized to FALSE.  For each table used by the image, the
+header-writing process emits the table and sets sent_table = TRUE unless it is
+already TRUE.  (In normal usage, this prevents outputting the same table
+definition multiple times, as would otherwise occur because the chroma
+components typically share tables.)  Thus, setting this field to TRUE before
+calling jpeg_start_compress() will prevent the table from being written at
+all.
+
+If you want to create a "pure" abbreviated image file containing no tables,
+just call "jpeg_suppress_tables(&cinfo, TRUE)" after constructing all the
+tables.  If you want to emit some but not all tables, you'll need to set the
+individual sent_table fields directly.
+
+To create an abbreviated image, you must also call jpeg_start_compress()
+with a second parameter of FALSE, not TRUE.  Otherwise jpeg_start_compress()
+will force all the sent_table fields to FALSE.  (This is a safety feature to
+prevent abbreviated images from being created accidentally.)
+
+To create a tables-only file, perform the same parameter setup that you
+normally would, but instead of calling jpeg_start_compress() and so on, call
+jpeg_write_tables(&cinfo).  This will write an abbreviated datastream
+containing only SOI, DQT and/or DHT markers, and EOI.  All the quantization
+and Huffman tables that are currently defined in the compression object will
+be emitted unless their sent_tables flag is already TRUE, and then all the
+sent_tables flags will be set TRUE.
+
+A sure-fire way to create matching tables-only and abbreviated image files
+is to proceed as follows:
+
+	create JPEG compression object
+	set JPEG parameters
+	set destination to tables-only file
+	jpeg_write_tables(&cinfo);
+	set destination to image file
+	jpeg_start_compress(&cinfo, FALSE);
+	write data...
+	jpeg_finish_compress(&cinfo);
+
+Since the JPEG parameters are not altered between writing the table file and
+the abbreviated image file, the same tables are sure to be used.  Of course,
+you can repeat the jpeg_start_compress() ... jpeg_finish_compress() sequence
+many times to produce many abbreviated image files matching the table file.
+
+You cannot suppress output of the computed Huffman tables when Huffman
+optimization is selected.  (If you could, there'd be no way to decode the
+image...)  Generally, you don't want to set optimize_coding = TRUE when
+you are trying to produce abbreviated files.
+
+In some cases you might want to compress an image using tables which are
+not stored in the application, but are defined in an interchange or
+tables-only file readable by the application.  This can be done by setting up
+a JPEG decompression object to read the specification file, then copying the
+tables into your compression object.  See jpeg_copy_critical_parameters()
+for an example of copying quantization tables.
+
+
+To read abbreviated image files, you simply need to load the proper tables
+into the decompression object before trying to read the abbreviated image.
+If the proper tables are stored in the application program, you can just
+allocate the table structs and fill in their contents directly.  For example,
+to load a fixed quantization table into table slot "n":
+
+    if (cinfo.quant_tbl_ptrs[n] == NULL)
+      cinfo.quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) &cinfo);
+    quant_ptr = cinfo.quant_tbl_ptrs[n];	/* quant_ptr is JQUANT_TBL* */
+    for (i = 0; i < 64; i++) {
+      /* Qtable[] is desired quantization table, in natural array order */
+      quant_ptr->quantval[i] = Qtable[i];
+    }
+
+Code to load a fixed Huffman table is typically (for AC table "n"):
+
+    if (cinfo.ac_huff_tbl_ptrs[n] == NULL)
+      cinfo.ac_huff_tbl_ptrs[n] = jpeg_alloc_huff_table((j_common_ptr) &cinfo);
+    huff_ptr = cinfo.ac_huff_tbl_ptrs[n];	/* huff_ptr is JHUFF_TBL* */
+    for (i = 1; i <= 16; i++) {
+      /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
+      huff_ptr->bits[i] = counts[i];
+    }
+    for (i = 0; i < 256; i++) {
+      /* symbols[] is the list of Huffman symbols, in code-length order */
+      huff_ptr->huffval[i] = symbols[i];
+    }
+
+(Note that trying to set cinfo.quant_tbl_ptrs[n] to point directly at a
+constant JQUANT_TBL object is not safe.  If the incoming file happened to
+contain a quantization table definition, your master table would get
+overwritten!  Instead allocate a working table copy and copy the master table
+into it, as illustrated above.  Ditto for Huffman tables, of course.)
+
+You might want to read the tables from a tables-only file, rather than
+hard-wiring them into your application.  The jpeg_read_header() call is
+sufficient to read a tables-only file.  You must pass a second parameter of
+FALSE to indicate that you do not require an image to be present.  Thus, the
+typical scenario is
+
+	create JPEG decompression object
+	set source to tables-only file
+	jpeg_read_header(&cinfo, FALSE);
+	set source to abbreviated image file
+	jpeg_read_header(&cinfo, TRUE);
+	set decompression parameters
+	jpeg_start_decompress(&cinfo);
+	read data...
+	jpeg_finish_decompress(&cinfo);
+
+In some cases, you may want to read a file without knowing whether it contains
+an image or just tables.  In that case, pass FALSE and check the return value
+from jpeg_read_header(): it will be JPEG_HEADER_OK if an image was found,
+JPEG_HEADER_TABLES_ONLY if only tables were found.  (A third return value,
+JPEG_SUSPENDED, is possible when using a suspending data source manager.)
+Note that jpeg_read_header() will not complain if you read an abbreviated
+image for which you haven't loaded the missing tables; the missing-table check
+occurs later, in jpeg_start_decompress().
+
+
+It is possible to read a series of images from a single source file by
+repeating the jpeg_read_header() ... jpeg_finish_decompress() sequence,
+without releasing/recreating the JPEG object or the data source module.
+(If you did reinitialize, any partial bufferload left in the data source
+buffer at the end of one image would be discarded, causing you to lose the
+start of the next image.)  When you use this method, stored tables are
+automatically carried forward, so some of the images can be abbreviated images
+that depend on tables from earlier images.
+
+If you intend to write a series of images into a single destination file,
+you might want to make a specialized data destination module that doesn't
+flush the output buffer at term_destination() time.  This would speed things
+up by some trifling amount.  Of course, you'd need to remember to flush the
+buffer after the last image.  You can make the later images be abbreviated
+ones by passing FALSE to jpeg_start_compress().
+
+
+Special markers
+---------------
+
+Some applications may need to insert or extract special data in the JPEG
+datastream.  The JPEG standard provides marker types "COM" (comment) and
+"APP0" through "APP15" (application) to hold application-specific data.
+Unfortunately, the use of these markers is not specified by the standard.
+COM markers are fairly widely used to hold user-supplied text.  The JFIF file
+format spec uses APP0 markers with specified initial strings to hold certain
+data.  Adobe applications use APP14 markers beginning with the string "Adobe"
+for miscellaneous data.  Other APPn markers are rarely seen, but might
+contain almost anything.
+
+If you wish to store user-supplied text, we recommend you use COM markers
+and place readable 7-bit ASCII text in them.  Newline conventions are not
+standardized --- expect to find LF (Unix style), CR/LF (DOS style), or CR
+(Mac style).  A robust COM reader should be able to cope with random binary
+garbage, including nulls, since some applications generate COM markers
+containing non-ASCII junk.  (But yours should not be one of them.)
+
+For program-supplied data, use an APPn marker, and be sure to begin it with an
+identifying string so that you can tell whether the marker is actually yours.
+It's probably best to avoid using APP0 or APP14 for any private markers.
+(NOTE: the upcoming SPIFF standard will use APP8 markers; we recommend you
+not use APP8 markers for any private purposes, either.)
+
+Keep in mind that at most 65533 bytes can be put into one marker, but you
+can have as many markers as you like.
+
+By default, the IJG compression library will write a JFIF APP0 marker if the
+selected JPEG colorspace is grayscale or YCbCr, or an Adobe APP14 marker if
+the selected colorspace is RGB, CMYK, or YCCK.  You can disable this, but
+we don't recommend it.  The decompression library will recognize JFIF and
+Adobe markers and will set the JPEG colorspace properly when one is found.
+
+
+You can write special markers immediately following the datastream header by
+calling jpeg_write_marker() after jpeg_start_compress() and before the first
+call to jpeg_write_scanlines().  When you do this, the markers appear after
+the SOI and the JFIF APP0 and Adobe APP14 markers (if written), but before
+all else.  Specify the marker type parameter as "JPEG_COM" for COM or
+"JPEG_APP0 + n" for APPn.  (Actually, jpeg_write_marker will let you write
+any marker type, but we don't recommend writing any other kinds of marker.)
+For example, to write a user comment string pointed to by comment_text:
+	jpeg_write_marker(cinfo, JPEG_COM, comment_text, strlen(comment_text));
+
+If it's not convenient to store all the marker data in memory at once,
+you can instead call jpeg_write_m_header() followed by multiple calls to
+jpeg_write_m_byte().  If you do it this way, it's your responsibility to
+call jpeg_write_m_byte() exactly the number of times given in the length
+parameter to jpeg_write_m_header().  (This method lets you empty the
+output buffer partway through a marker, which might be important when
+using a suspending data destination module.  In any case, if you are using
+a suspending destination, you should flush its buffer after inserting
+any special markers.  See "I/O suspension".)
+
+Or, if you prefer to synthesize the marker byte sequence yourself,
+you can just cram it straight into the data destination module.
+
+If you are writing JFIF 1.02 extension markers (thumbnail images), don't
+forget to set cinfo.JFIF_minor_version = 2 so that the encoder will write the
+correct JFIF version number in the JFIF header marker.  The library's default
+is to write version 1.01, but that's wrong if you insert any 1.02 extension
+markers.  (We could probably get away with just defaulting to 1.02, but there
+used to be broken decoders that would complain about unknown minor version
+numbers.  To reduce compatibility risks it's safest not to write 1.02 unless
+you are actually using 1.02 extensions.)
+
+
+When reading, two methods of handling special markers are available:
+1. You can ask the library to save the contents of COM and/or APPn markers
+into memory, and then examine them at your leisure afterwards.
+2. You can supply your own routine to process COM and/or APPn markers
+on-the-fly as they are read.
+The first method is simpler to use, especially if you are using a suspending
+data source; writing a marker processor that copes with input suspension is
+not easy (consider what happens if the marker is longer than your available
+input buffer).  However, the second method conserves memory since the marker
+data need not be kept around after it's been processed.
+
+For either method, you'd normally set up marker handling after creating a
+decompression object and before calling jpeg_read_header(), because the
+markers of interest will typically be near the head of the file and so will
+be scanned by jpeg_read_header.  Once you've established a marker handling
+method, it will be used for the life of that decompression object
+(potentially many datastreams), unless you change it.  Marker handling is
+determined separately for COM markers and for each APPn marker code.
+
+
+To save the contents of special markers in memory, call
+	jpeg_save_markers(cinfo, marker_code, length_limit)
+where marker_code is the marker type to save, JPEG_COM or JPEG_APP0+n.
+(To arrange to save all the special marker types, you need to call this
+routine 17 times, for COM and APP0-APP15.)  If the incoming marker is longer
+than length_limit data bytes, only length_limit bytes will be saved; this
+parameter allows you to avoid chewing up memory when you only need to see the
+first few bytes of a potentially large marker.  If you want to save all the
+data, set length_limit to 0xFFFF; that is enough since marker lengths are only
+16 bits.  As a special case, setting length_limit to 0 prevents that marker
+type from being saved at all.  (That is the default behavior, in fact.)
+
+After jpeg_read_header() completes, you can examine the special markers by
+following the cinfo->marker_list pointer chain.  All the special markers in
+the file appear in this list, in order of their occurrence in the file (but
+omitting any markers of types you didn't ask for).  Both the original data
+length and the saved data length are recorded for each list entry; the latter
+will not exceed length_limit for the particular marker type.  Note that these
+lengths exclude the marker length word, whereas the stored representation
+within the JPEG file includes it.  (Hence the maximum data length is really
+only 65533.)
+
+It is possible that additional special markers appear in the file beyond the
+SOS marker at which jpeg_read_header stops; if so, the marker list will be
+extended during reading of the rest of the file.  This is not expected to be
+common, however.  If you are short on memory you may want to reset the length
+limit to zero for all marker types after finishing jpeg_read_header, to
+ensure that the max_memory_to_use setting cannot be exceeded due to addition
+of later markers.
+
+The marker list remains stored until you call jpeg_finish_decompress or
+jpeg_abort, at which point the memory is freed and the list is set to empty.
+(jpeg_destroy also releases the storage, of course.)
+
+Note that the library is internally interested in APP0 and APP14 markers;
+if you try to set a small nonzero length limit on these types, the library
+will silently force the length up to the minimum it wants.  (But you can set
+a zero length limit to prevent them from being saved at all.)  Also, in a
+16-bit environment, the maximum length limit may be constrained to less than
+65533 by malloc() limitations.  It is therefore best not to assume that the
+effective length limit is exactly what you set it to be.
+
+
+If you want to supply your own marker-reading routine, you do it by calling
+jpeg_set_marker_processor().  A marker processor routine must have the
+signature
+	boolean jpeg_marker_parser_method (j_decompress_ptr cinfo)
+Although the marker code is not explicitly passed, the routine can find it
+in cinfo->unread_marker.  At the time of call, the marker proper has been
+read from the data source module.  The processor routine is responsible for
+reading the marker length word and the remaining parameter bytes, if any.
+Return TRUE to indicate success.  (FALSE should be returned only if you are
+using a suspending data source and it tells you to suspend.  See the standard
+marker processors in jdmarker.c for appropriate coding methods if you need to
+use a suspending data source.)
+
+If you override the default APP0 or APP14 processors, it is up to you to
+recognize JFIF and Adobe markers if you want colorspace recognition to occur
+properly.  We recommend copying and extending the default processors if you
+want to do that.  (A better idea is to save these marker types for later
+examination by calling jpeg_save_markers(); that method doesn't interfere
+with the library's own processing of these markers.)
+
+jpeg_set_marker_processor() and jpeg_save_markers() are mutually exclusive
+--- if you call one it overrides any previous call to the other, for the
+particular marker type specified.
+
+A simple example of an external COM processor can be found in djpeg.c.
+Also, see jpegtran.c for an example of using jpeg_save_markers.
+
+
+Raw (downsampled) image data
+----------------------------
+
+Some applications need to supply already-downsampled image data to the JPEG
+compressor, or to receive raw downsampled data from the decompressor.  The
+library supports this requirement by allowing the application to write or
+read raw data, bypassing the normal preprocessing or postprocessing steps.
+The interface is different from the standard one and is somewhat harder to
+use.  If your interest is merely in bypassing color conversion, we recommend
+that you use the standard interface and simply set jpeg_color_space =
+in_color_space (or jpeg_color_space = out_color_space for decompression).
+The mechanism described in this section is necessary only to supply or
+receive downsampled image data, in which not all components have the same
+dimensions.
+
+
+To compress raw data, you must supply the data in the colorspace to be used
+in the JPEG file (please read the earlier section on Special color spaces)
+and downsampled to the sampling factors specified in the JPEG parameters.
+You must supply the data in the format used internally by the JPEG library,
+namely a JSAMPIMAGE array.  This is an array of pointers to two-dimensional
+arrays, each of type JSAMPARRAY.  Each 2-D array holds the values for one
+color component.  This structure is necessary since the components are of
+different sizes.  If the image dimensions are not a multiple of the MCU size,
+you must also pad the data correctly (usually, this is done by replicating
+the last column and/or row).  The data must be padded to a multiple of a DCT
+block in each component: that is, each downsampled row must contain a
+multiple of 8 valid samples, and there must be a multiple of 8 sample rows
+for each component.  (For applications such as conversion of digital TV
+images, the standard image size is usually a multiple of the DCT block size,
+so that no padding need actually be done.)
+
+The procedure for compression of raw data is basically the same as normal
+compression, except that you call jpeg_write_raw_data() in place of
+jpeg_write_scanlines().  Before calling jpeg_start_compress(), you must do
+the following:
+  * Set cinfo->raw_data_in to TRUE.  (It is set FALSE by jpeg_set_defaults().)
+    This notifies the library that you will be supplying raw data.
+  * Ensure jpeg_color_space is correct --- an explicit jpeg_set_colorspace()
+    call is a good idea.  Note that since color conversion is bypassed,
+    in_color_space is ignored, except that jpeg_set_defaults() uses it to
+    choose the default jpeg_color_space setting.
+  * Ensure the sampling factors, cinfo->comp_info[i].h_samp_factor and
+    cinfo->comp_info[i].v_samp_factor, are correct.  Since these indicate the
+    dimensions of the data you are supplying, it's wise to set them
+    explicitly, rather than assuming the library's defaults are what you want.
+
+To pass raw data to the library, call jpeg_write_raw_data() in place of
+jpeg_write_scanlines().  The two routines work similarly except that
+jpeg_write_raw_data takes a JSAMPIMAGE data array rather than JSAMPARRAY.
+The scanlines count passed to and returned from jpeg_write_raw_data is
+measured in terms of the component with the largest v_samp_factor.
+
+jpeg_write_raw_data() processes one MCU row per call, which is to say
+v_samp_factor*DCTSIZE sample rows of each component.  The passed num_lines
+value must be at least max_v_samp_factor*DCTSIZE, and the return value will
+be exactly that amount (or possibly some multiple of that amount, in future
+library versions).  This is true even on the last call at the bottom of the
+image; don't forget to pad your data as necessary.
+
+The required dimensions of the supplied data can be computed for each
+component as
+	cinfo->comp_info[i].width_in_blocks*DCTSIZE  samples per row
+	cinfo->comp_info[i].height_in_blocks*DCTSIZE rows in image
+after jpeg_start_compress() has initialized those fields.  If the valid data
+is smaller than this, it must be padded appropriately.  For some sampling
+factors and image sizes, additional dummy DCT blocks are inserted to make
+the image a multiple of the MCU dimensions.  The library creates such dummy
+blocks itself; it does not read them from your supplied data.  Therefore you
+need never pad by more than DCTSIZE samples.  An example may help here.
+Assume 2h2v downsampling of YCbCr data, that is
+	cinfo->comp_info[0].h_samp_factor = 2		for Y
+	cinfo->comp_info[0].v_samp_factor = 2
+	cinfo->comp_info[1].h_samp_factor = 1		for Cb
+	cinfo->comp_info[1].v_samp_factor = 1
+	cinfo->comp_info[2].h_samp_factor = 1		for Cr
+	cinfo->comp_info[2].v_samp_factor = 1
+and suppose that the nominal image dimensions (cinfo->image_width and
+cinfo->image_height) are 101x101 pixels.  Then jpeg_start_compress() will
+compute downsampled_width = 101 and width_in_blocks = 13 for Y,
+downsampled_width = 51 and width_in_blocks = 7 for Cb and Cr (and the same
+for the height fields).  You must pad the Y data to at least 13*8 = 104
+columns and rows, the Cb/Cr data to at least 7*8 = 56 columns and rows.  The
+MCU height is max_v_samp_factor = 2 DCT rows so you must pass at least 16
+scanlines on each call to jpeg_write_raw_data(), which is to say 16 actual
+sample rows of Y and 8 each of Cb and Cr.  A total of 7 MCU rows are needed,
+so you must pass a total of 7*16 = 112 "scanlines".  The last DCT block row
+of Y data is dummy, so it doesn't matter what you pass for it in the data
+arrays, but the scanlines count must total up to 112 so that all of the Cb
+and Cr data gets passed.
+
+Output suspension is supported with raw-data compression: if the data
+destination module suspends, jpeg_write_raw_data() will return 0.
+In this case the same data rows must be passed again on the next call.
+
+
+Decompression with raw data output implies bypassing all postprocessing:
+you cannot ask for rescaling or color quantization, for instance.  More
+seriously, you must deal with the color space and sampling factors present in
+the incoming file.  If your application only handles, say, 2h1v YCbCr data,
+you must check for and fail on other color spaces or other sampling factors.
+The library will not convert to a different color space for you.
+
+To obtain raw data output, set cinfo->raw_data_out = TRUE before
+jpeg_start_decompress() (it is set FALSE by jpeg_read_header()).  Be sure to
+verify that the color space and sampling factors are ones you can handle.
+Then call jpeg_read_raw_data() in place of jpeg_read_scanlines().  The
+decompression process is otherwise the same as usual.
+
+jpeg_read_raw_data() returns one MCU row per call, and thus you must pass a
+buffer of at least max_v_samp_factor*DCTSIZE scanlines (scanline counting is
+the same as for raw-data compression).  The buffer you pass must be large
+enough to hold the actual data plus padding to DCT-block boundaries.  As with
+compression, any entirely dummy DCT blocks are not processed so you need not
+allocate space for them, but the total scanline count includes them.  The
+above example of computing buffer dimensions for raw-data compression is
+equally valid for decompression.
+
+Input suspension is supported with raw-data decompression: if the data source
+module suspends, jpeg_read_raw_data() will return 0.  You can also use
+buffered-image mode to read raw data in multiple passes.
+
+
+Really raw data: DCT coefficients
+---------------------------------
+
+It is possible to read or write the contents of a JPEG file as raw DCT
+coefficients.  This facility is mainly intended for use in lossless
+transcoding between different JPEG file formats.  Other possible applications
+include lossless cropping of a JPEG image, lossless reassembly of a
+multi-strip or multi-tile TIFF/JPEG file into a single JPEG datastream, etc.
+
+To read the contents of a JPEG file as DCT coefficients, open the file and do
+jpeg_read_header() as usual.  But instead of calling jpeg_start_decompress()
+and jpeg_read_scanlines(), call jpeg_read_coefficients().  This will read the
+entire image into a set of virtual coefficient-block arrays, one array per
+component.  The return value is a pointer to an array of virtual-array
+descriptors.  Each virtual array can be accessed directly using the JPEG
+memory manager's access_virt_barray method (see Memory management, below,
+and also read structure.doc's discussion of virtual array handling).  Or,
+for simple transcoding to a different JPEG file format, the array list can
+just be handed directly to jpeg_write_coefficients().
+
+Each block in the block arrays contains quantized coefficient values in
+normal array order (not JPEG zigzag order).  The block arrays contain only
+DCT blocks containing real data; any entirely-dummy blocks added to fill out
+interleaved MCUs at the right or bottom edges of the image are discarded
+during reading and are not stored in the block arrays.  (The size of each
+block array can be determined from the width_in_blocks and height_in_blocks
+fields of the component's comp_info entry.)  This is also the data format
+expected by jpeg_write_coefficients().
+
+When you are done using the virtual arrays, call jpeg_finish_decompress()
+to release the array storage and return the decompression object to an idle
+state; or just call jpeg_destroy() if you don't need to reuse the object.
+
+If you use a suspending data source, jpeg_read_coefficients() will return
+NULL if it is forced to suspend; a non-NULL return value indicates successful
+completion.  You need not test for a NULL return value when using a
+non-suspending data source.
+
+It is also possible to call jpeg_read_coefficients() to obtain access to the
+decoder's coefficient arrays during a normal decode cycle in buffered-image
+mode.  This frammish might be useful for progressively displaying an incoming
+image and then re-encoding it without loss.  To do this, decode in buffered-
+image mode as discussed previously, then call jpeg_read_coefficients() after
+the last jpeg_finish_output() call.  The arrays will be available for your use
+until you call jpeg_finish_decompress().
+
+
+To write the contents of a JPEG file as DCT coefficients, you must provide
+the DCT coefficients stored in virtual block arrays.  You can either pass
+block arrays read from an input JPEG file by jpeg_read_coefficients(), or
+allocate virtual arrays from the JPEG compression object and fill them
+yourself.  In either case, jpeg_write_coefficients() is substituted for
+jpeg_start_compress() and jpeg_write_scanlines().  Thus the sequence is
+  * Create compression object
+  * Set all compression parameters as necessary
+  * Request virtual arrays if needed
+  * jpeg_write_coefficients()
+  * jpeg_finish_compress()
+  * Destroy or re-use compression object
+jpeg_write_coefficients() is passed a pointer to an array of virtual block
+array descriptors; the number of arrays is equal to cinfo.num_components.
+
+The virtual arrays need only have been requested, not realized, before
+jpeg_write_coefficients() is called.  A side-effect of
+jpeg_write_coefficients() is to realize any virtual arrays that have been
+requested from the compression object's memory manager.  Thus, when obtaining
+the virtual arrays from the compression object, you should fill the arrays
+after calling jpeg_write_coefficients().  The data is actually written out
+when you call jpeg_finish_compress(); jpeg_write_coefficients() only writes
+the file header.
+
+When writing raw DCT coefficients, it is crucial that the JPEG quantization
+tables and sampling factors match the way the data was encoded, or the
+resulting file will be invalid.  For transcoding from an existing JPEG file,
+we recommend using jpeg_copy_critical_parameters().  This routine initializes
+all the compression parameters to default values (like jpeg_set_defaults()),
+then copies the critical information from a source decompression object.
+The decompression object should have just been used to read the entire
+JPEG input file --- that is, it should be awaiting jpeg_finish_decompress().
+
+jpeg_write_coefficients() marks all tables stored in the compression object
+as needing to be written to the output file (thus, it acts like
+jpeg_start_compress(cinfo, TRUE)).  This is for safety's sake, to avoid
+emitting abbreviated JPEG files by accident.  If you really want to emit an
+abbreviated JPEG file, call jpeg_suppress_tables(), or set the tables'
+individual sent_table flags, between calling jpeg_write_coefficients() and
+jpeg_finish_compress().
+
+
+Progress monitoring
+-------------------
+
+Some applications may need to regain control from the JPEG library every so
+often.  The typical use of this feature is to produce a percent-done bar or
+other progress display.  (For a simple example, see cjpeg.c or djpeg.c.)
+Although you do get control back frequently during the data-transferring pass
+(the jpeg_read_scanlines or jpeg_write_scanlines loop), any additional passes
+will occur inside jpeg_finish_compress or jpeg_start_decompress; those
+routines may take a long time to execute, and you don't get control back
+until they are done.
+
+You can define a progress-monitor routine which will be called periodically
+by the library.  No guarantees are made about how often this call will occur,
+so we don't recommend you use it for mouse tracking or anything like that.
+At present, a call will occur once per MCU row, scanline, or sample row
+group, whichever unit is convenient for the current processing mode; so the
+wider the image, the longer the time between calls.  During the data
+transferring pass, only one call occurs per call of jpeg_read_scanlines or
+jpeg_write_scanlines, so don't pass a large number of scanlines at once if
+you want fine resolution in the progress count.  (If you really need to use
+the callback mechanism for time-critical tasks like mouse tracking, you could
+insert additional calls inside some of the library's inner loops.)
+
+To establish a progress-monitor callback, create a struct jpeg_progress_mgr,
+fill in its progress_monitor field with a pointer to your callback routine,
+and set cinfo->progress to point to the struct.  The callback will be called
+whenever cinfo->progress is non-NULL.  (This pointer is set to NULL by
+jpeg_create_compress or jpeg_create_decompress; the library will not change
+it thereafter.  So if you allocate dynamic storage for the progress struct,
+make sure it will live as long as the JPEG object does.  Allocating from the
+JPEG memory manager with lifetime JPOOL_PERMANENT will work nicely.)  You
+can use the same callback routine for both compression and decompression.
+
+The jpeg_progress_mgr struct contains four fields which are set by the library:
+	long pass_counter;	/* work units completed in this pass */
+	long pass_limit;	/* total number of work units in this pass */
+	int completed_passes;	/* passes completed so far */
+	int total_passes;	/* total number of passes expected */
+During any one pass, pass_counter increases from 0 up to (not including)
+pass_limit; the step size is usually but not necessarily 1.  The pass_limit
+value may change from one pass to another.  The expected total number of
+passes is in total_passes, and the number of passes already completed is in
+completed_passes.  Thus the fraction of work completed may be estimated as
+		completed_passes + (pass_counter/pass_limit)
+		--------------------------------------------
+				total_passes
+ignoring the fact that the passes may not be equal amounts of work.
+
+When decompressing, pass_limit can even change within a pass, because it
+depends on the number of scans in the JPEG file, which isn't always known in
+advance.  The computed fraction-of-work-done may jump suddenly (if the library
+discovers it has overestimated the number of scans) or even decrease (in the
+opposite case).  It is not wise to put great faith in the work estimate.
+
+When using the decompressor's buffered-image mode, the progress monitor work
+estimate is likely to be completely unhelpful, because the library has no way
+to know how many output passes will be demanded of it.  Currently, the library
+sets total_passes based on the assumption that there will be one more output
+pass if the input file end hasn't yet been read (jpeg_input_complete() isn't
+TRUE), but no more output passes if the file end has been reached when the
+output pass is started.  This means that total_passes will rise as additional
+output passes are requested.  If you have a way of determining the input file
+size, estimating progress based on the fraction of the file that's been read
+will probably be more useful than using the library's value.
+
+
+Memory management
+-----------------
+
+This section covers some key facts about the JPEG library's built-in memory
+manager.  For more info, please read structure.doc's section about the memory
+manager, and consult the source code if necessary.
+
+All memory and temporary file allocation within the library is done via the
+memory manager.  If necessary, you can replace the "back end" of the memory
+manager to control allocation yourself (for example, if you don't want the
+library to use malloc() and free() for some reason).
+
+Some data is allocated "permanently" and will not be freed until the JPEG
+object is destroyed.  Most data is allocated "per image" and is freed by
+jpeg_finish_compress, jpeg_finish_decompress, or jpeg_abort.  You can call the
+memory manager yourself to allocate structures that will automatically be
+freed at these times.  Typical code for this is
+  ptr = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, size);
+Use JPOOL_PERMANENT to get storage that lasts as long as the JPEG object.
+Use alloc_large instead of alloc_small for anything bigger than a few Kbytes.
+There are also alloc_sarray and alloc_barray routines that automatically
+build 2-D sample or block arrays.
+
+The library's minimum space requirements to process an image depend on the
+image's width, but not on its height, because the library ordinarily works
+with "strip" buffers that are as wide as the image but just a few rows high.
+Some operating modes (eg, two-pass color quantization) require full-image
+buffers.  Such buffers are treated as "virtual arrays": only the current strip
+need be in memory, and the rest can be swapped out to a temporary file.
+
+If you use the simplest memory manager back end (jmemnobs.c), then no
+temporary files are used; virtual arrays are simply malloc()'d.  Images bigger
+than memory can be processed only if your system supports virtual memory.
+The other memory manager back ends support temporary files of various flavors
+and thus work in machines without virtual memory.  They may also be useful on
+Unix machines if you need to process images that exceed available swap space.
+
+When using temporary files, the library will make the in-memory buffers for
+its virtual arrays just big enough to stay within a "maximum memory" setting.
+Your application can set this limit by setting cinfo->mem->max_memory_to_use
+after creating the JPEG object.  (Of course, there is still a minimum size for
+the buffers, so the max-memory setting is effective only if it is bigger than
+the minimum space needed.)  If you allocate any large structures yourself, you
+must allocate them before jpeg_start_compress() or jpeg_start_decompress() in
+order to have them counted against the max memory limit.  Also keep in mind
+that space allocated with alloc_small() is ignored, on the assumption that
+it's too small to be worth worrying about; so a reasonable safety margin
+should be left when setting max_memory_to_use.
+
+If you use the jmemname.c or jmemdos.c memory manager back end, it is
+important to clean up the JPEG object properly to ensure that the temporary
+files get deleted.  (This is especially crucial with jmemdos.c, where the
+"temporary files" may be extended-memory segments; if they are not freed,
+DOS will require a reboot to recover the memory.)  Thus, with these memory
+managers, it's a good idea to provide a signal handler that will trap any
+early exit from your program.  The handler should call either jpeg_abort()
+or jpeg_destroy() for any active JPEG objects.  A handler is not needed with
+jmemnobs.c, and shouldn't be necessary with jmemansi.c or jmemmac.c either,
+since the C library is supposed to take care of deleting files made with
+tmpfile().
+
+
+Memory usage
+------------
+
+Working memory requirements while performing compression or decompression
+depend on image dimensions, image characteristics (such as colorspace and
+JPEG process), and operating mode (application-selected options).
+
+As of v6b, the decompressor requires:
+ 1. About 24K in more-or-less-fixed-size data.  This varies a bit depending
+    on operating mode and image characteristics (particularly color vs.
+    grayscale), but it doesn't depend on image dimensions.
+ 2. Strip buffers (of size proportional to the image width) for IDCT and
+    upsampling results.  The worst case for commonly used sampling factors
+    is about 34 bytes * width in pixels for a color image.  A grayscale image
+    only needs about 8 bytes per pixel column.
+ 3. A full-image DCT coefficient buffer is needed to decode a multi-scan JPEG
+    file (including progressive JPEGs), or whenever you select buffered-image
+    mode.  This takes 2 bytes/coefficient.  At typical 2x2 sampling, that's
+    3 bytes per pixel for a color image.  Worst case (1x1 sampling) requires
+    6 bytes/pixel.  For grayscale, figure 2 bytes/pixel.
+ 4. To perform 2-pass color quantization, the decompressor also needs a
+    128K color lookup table and a full-image pixel buffer (3 bytes/pixel).
+This does not count any memory allocated by the application, such as a
+buffer to hold the final output image.
+
+The above figures are valid for 8-bit JPEG data precision and a machine with
+32-bit ints.  For 12-bit JPEG data, double the size of the strip buffers and
+quantization pixel buffer.  The "fixed-size" data will be somewhat smaller
+with 16-bit ints, larger with 64-bit ints.  Also, CMYK or other unusual
+color spaces will require different amounts of space.
+
+The full-image coefficient and pixel buffers, if needed at all, do not
+have to be fully RAM resident; you can have the library use temporary
+files instead when the total memory usage would exceed a limit you set.
+(But if your OS supports virtual memory, it's probably better to just use
+jmemnobs and let the OS do the swapping.)
+
+The compressor's memory requirements are similar, except that it has no need
+for color quantization.  Also, it needs a full-image DCT coefficient buffer
+if Huffman-table optimization is asked for, even if progressive mode is not
+requested.
+
+If you need more detailed information about memory usage in a particular
+situation, you can enable the MEM_STATS code in jmemmgr.c.
+
+
+Library compile-time options
+----------------------------
+
+A number of compile-time options are available by modifying jmorecfg.h.
+
+The JPEG standard provides for both the baseline 8-bit DCT process and
+a 12-bit DCT process.  The IJG code supports 12-bit lossy JPEG if you define
+BITS_IN_JSAMPLE as 12 rather than 8.  Note that this causes JSAMPLE to be
+larger than a char, so it affects the surrounding application's image data.
+The sample applications cjpeg and djpeg can support 12-bit mode only for PPM
+and GIF file formats; you must disable the other file formats to compile a
+12-bit cjpeg or djpeg.  (install.doc has more information about that.)
+At present, a 12-bit library can handle *only* 12-bit images, not both
+precisions.  (If you need to include both 8- and 12-bit libraries in a single
+application, you could probably do it by defining NEED_SHORT_EXTERNAL_NAMES
+for just one of the copies.  You'd have to access the 8-bit and 12-bit copies
+from separate application source files.  This is untested ... if you try it,
+we'd like to hear whether it works!)
+
+Note that a 12-bit library always compresses in Huffman optimization mode,
+in order to generate valid Huffman tables.  This is necessary because our
+default Huffman tables only cover 8-bit data.  If you need to output 12-bit
+files in one pass, you'll have to supply suitable default Huffman tables.
+You may also want to supply your own DCT quantization tables; the existing
+quality-scaling code has been developed for 8-bit use, and probably doesn't
+generate especially good tables for 12-bit.
+
+The maximum number of components (color channels) in the image is determined
+by MAX_COMPONENTS.  The JPEG standard allows up to 255 components, but we
+expect that few applications will need more than four or so.
+
+On machines with unusual data type sizes, you may be able to improve
+performance or reduce memory space by tweaking the various typedefs in
+jmorecfg.h.  In particular, on some RISC CPUs, access to arrays of "short"s
+is quite slow; consider trading memory for speed by making JCOEF, INT16, and
+UINT16 be "int" or "unsigned int".  UINT8 is also a candidate to become int.
+You probably don't want to make JSAMPLE be int unless you have lots of memory
+to burn.
+
+You can reduce the size of the library by compiling out various optional
+functions.  To do this, undefine xxx_SUPPORTED symbols as necessary.
+
+You can also save a few K by not having text error messages in the library;
+the standard error message table occupies about 5Kb.  This is particularly
+reasonable for embedded applications where there's no good way to display 
+a message anyway.  To do this, remove the creation of the message table
+(jpeg_std_message_table[]) from jerror.c, and alter format_message to do
+something reasonable without it.  You could output the numeric value of the
+message code number, for example.  If you do this, you can also save a couple
+more K by modifying the TRACEMSn() macros in jerror.h to expand to nothing;
+you don't need trace capability anyway, right?
+
+
+Portability considerations
+--------------------------
+
+The JPEG library has been written to be extremely portable; the sample
+applications cjpeg and djpeg are slightly less so.  This section summarizes
+the design goals in this area.  (If you encounter any bugs that cause the
+library to be less portable than is claimed here, we'd appreciate hearing
+about them.)
+
+The code works fine on ANSI C, C++, and pre-ANSI C compilers, using any of
+the popular system include file setups, and some not-so-popular ones too.
+See install.doc for configuration procedures.
+
+The code is not dependent on the exact sizes of the C data types.  As
+distributed, we make the assumptions that
+	char	is at least 8 bits wide
+	short	is at least 16 bits wide
+	int	is at least 16 bits wide
+	long	is at least 32 bits wide
+(These are the minimum requirements of the ANSI C standard.)  Wider types will
+work fine, although memory may be used inefficiently if char is much larger
+than 8 bits or short is much bigger than 16 bits.  The code should work
+equally well with 16- or 32-bit ints.
+
+In a system where these assumptions are not met, you may be able to make the
+code work by modifying the typedefs in jmorecfg.h.  However, you will probably
+have difficulty if int is less than 16 bits wide, since references to plain
+int abound in the code.
+
+char can be either signed or unsigned, although the code runs faster if an
+unsigned char type is available.  If char is wider than 8 bits, you will need
+to redefine JOCTET and/or provide custom data source/destination managers so
+that JOCTET represents exactly 8 bits of data on external storage.
+
+The JPEG library proper does not assume ASCII representation of characters.
+But some of the image file I/O modules in cjpeg/djpeg do have ASCII
+dependencies in file-header manipulation; so does cjpeg's select_file_type()
+routine.
+
+The JPEG library does not rely heavily on the C library.  In particular, C
+stdio is used only by the data source/destination modules and the error
+handler, all of which are application-replaceable.  (cjpeg/djpeg are more
+heavily dependent on stdio.)  malloc and free are called only from the memory
+manager "back end" module, so you can use a different memory allocator by
+replacing that one file.
+
+The code generally assumes that C names must be unique in the first 15
+characters.  However, global function names can be made unique in the
+first 6 characters by defining NEED_SHORT_EXTERNAL_NAMES.
+
+More info about porting the code may be gleaned by reading jconfig.doc,
+jmorecfg.h, and jinclude.h.
+
+
+Notes for MS-DOS implementors
+-----------------------------
+
+The IJG code is designed to work efficiently in 80x86 "small" or "medium"
+memory models (i.e., data pointers are 16 bits unless explicitly declared
+"far"; code pointers can be either size).  You may be able to use small
+model to compile cjpeg or djpeg by itself, but you will probably have to use
+medium model for any larger application.  This won't make much difference in
+performance.  You *will* take a noticeable performance hit if you use a
+large-data memory model (perhaps 10%-25%), and you should avoid "huge" model
+if at all possible.
+
+The JPEG library typically needs 2Kb-3Kb of stack space.  It will also
+malloc about 20K-30K of near heap space while executing (and lots of far
+heap, but that doesn't count in this calculation).  This figure will vary
+depending on selected operating mode, and to a lesser extent on image size.
+There is also about 5Kb-6Kb of constant data which will be allocated in the
+near data segment (about 4Kb of this is the error message table).
+Thus you have perhaps 20K available for other modules' static data and near
+heap space before you need to go to a larger memory model.  The C library's
+static data will account for several K of this, but that still leaves a good
+deal for your needs.  (If you are tight on space, you could reduce the sizes
+of the I/O buffers allocated by jdatasrc.c and jdatadst.c, say from 4K to
+1K.  Another possibility is to move the error message table to far memory;
+this should be doable with only localized hacking on jerror.c.)
+
+About 2K of the near heap space is "permanent" memory that will not be
+released until you destroy the JPEG object.  This is only an issue if you
+save a JPEG object between compression or decompression operations.
+
+Far data space may also be a tight resource when you are dealing with large
+images.  The most memory-intensive case is decompression with two-pass color
+quantization, or single-pass quantization to an externally supplied color
+map.  This requires a 128Kb color lookup table plus strip buffers amounting
+to about 40 bytes per column for typical sampling ratios (eg, about 25600
+bytes for a 640-pixel-wide image).  You may not be able to process wide
+images if you have large data structures of your own.
+
+Of course, all of these concerns vanish if you use a 32-bit flat-memory-model
+compiler, such as DJGPP or Watcom C.  We highly recommend flat model if you
+can use it; the JPEG library is significantly faster in flat model.
diff --git a/Utilities/ITK/Utilities/itkjpeg/mangle_jpeg12bits.h b/Utilities/ITK/Utilities/itkjpeg/mangle_jpeg12bits.h
new file mode 100644
index 0000000000000000000000000000000000000000..d2189c7b091e70be4b0039f6ca8b62203427bc80
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/mangle_jpeg12bits.h
@@ -0,0 +1,141 @@
+#ifndef itk_jpeg12_mangle_h
+#define itk_jpeg12_mangle_h
+
+/* 
+
+This header file mangles all symbols exported from the jpeg library.
+It is included in all files while building the jpeg library.  Due to
+namespace pollution, no jpeg headers should be included in .h files in
+GDCM. This also allows us to generate two jpeg library (8bits and 12bits).
+
+The following command was used to obtain the symbol list:
+
+nm libitkitk_jpeg12.a | grep " [R|T] " | colrm 1 11 | sort
+
+(actually copy/paste from jpeg8bits)
+*/
+
+
+
+#define jcopy_block_row itk_jpeg12_jcopy_block_row
+#define jcopy_sample_rows itk_jpeg12_jcopy_sample_rows
+#define jdiv_round_up itk_jpeg12_jdiv_round_up
+#define jinit_1pass_quantizer itk_jpeg12_jinit_1pass_quantizer
+#define jinit_2pass_quantizer itk_jpeg12_jinit_2pass_quantizer
+#define jinit_arith_decoder itk_jpeg12_jinit_arith_decoder
+#define jinit_arith_encoder itk_jpeg12_jinit_arith_encoder
+#define jinit_c_codec itk_jpeg12_jinit_c_codec
+#define jinit_c_coef_controller itk_jpeg12_jinit_c_coef_controller
+#define jinit_c_diff_controller itk_jpeg12_jinit_c_diff_controller
+#define jinit_c_main_controller itk_jpeg12_jinit_c_main_controller
+#define jinit_c_master_control itk_jpeg12_jinit_c_master_control
+#define jinit_c_prep_controller itk_jpeg12_jinit_c_prep_controller
+#define jinit_c_scaler itk_jpeg12_jinit_c_scaler
+#define jinit_color_converter itk_jpeg12_jinit_color_converter
+#define jinit_color_deconverter itk_jpeg12_jinit_color_deconverter
+#define jinit_compress_master itk_jpeg12_jinit_compress_master
+#define jinit_d_codec itk_jpeg12_jinit_d_codec
+#define jinit_d_coef_controller itk_jpeg12_jinit_d_coef_controller
+#define jinit_d_diff_controller itk_jpeg12_jinit_d_diff_controller
+#define jinit_d_main_controller itk_jpeg12_jinit_d_main_controller
+#define jinit_d_post_controller itk_jpeg12_jinit_d_post_controller
+#define jinit_d_scaler itk_jpeg12_jinit_d_scaler
+#define jinit_differencer itk_jpeg12_jinit_differencer
+#define jinit_downsampler itk_jpeg12_jinit_downsampler
+#define jinit_forward_dct itk_jpeg12_jinit_forward_dct
+#define jinit_input_controller itk_jpeg12_jinit_input_controller
+#define jinit_inverse_dct itk_jpeg12_jinit_inverse_dct
+#define jinit_lhuff_decoder itk_jpeg12_jinit_lhuff_decoder
+#define jinit_lhuff_encoder itk_jpeg12_jinit_lhuff_encoder
+#define jinit_lossless_c_codec itk_jpeg12_jinit_lossless_c_codec
+#define jinit_lossless_d_codec itk_jpeg12_jinit_lossless_d_codec
+#define jinit_lossy_c_codec itk_jpeg12_jinit_lossy_c_codec
+#define jinit_lossy_d_codec itk_jpeg12_jinit_lossy_d_codec
+#define jinit_marker_reader itk_jpeg12_jinit_marker_reader
+#define jinit_marker_writer itk_jpeg12_jinit_marker_writer
+#define jinit_master_decompress itk_jpeg12_jinit_master_decompress
+#define jinit_memory_mgr itk_jpeg12_jinit_memory_mgr
+#define jinit_merged_upsampler itk_jpeg12_jinit_merged_upsampler
+#define jinit_phuff_decoder itk_jpeg12_jinit_phuff_decoder
+#define jinit_phuff_encoder itk_jpeg12_jinit_phuff_encoder
+#define jinit_shuff_decoder itk_jpeg12_jinit_shuff_decoder
+#define jinit_shuff_encoder itk_jpeg12_jinit_shuff_encoder
+#define jinit_undifferencer itk_jpeg12_jinit_undifferencer
+#define jinit_upsampler itk_jpeg12_jinit_upsampler
+#define jpeg_CreateCompress itk_jpeg12_jpeg_CreateCompress
+#define jpeg_CreateDecompress itk_jpeg12_jpeg_CreateDecompress
+#define jpeg_abort itk_jpeg12_jpeg_abort
+#define jpeg_abort_compress itk_jpeg12_jpeg_abort_compress
+#define jpeg_abort_decompress itk_jpeg12_jpeg_abort_decompress
+#define jpeg_add_quant_table itk_jpeg12_jpeg_add_quant_table
+#define jpeg_alloc_huff_table itk_jpeg12_jpeg_alloc_huff_table
+#define jpeg_alloc_quant_table itk_jpeg12_jpeg_alloc_quant_table
+#define jpeg_calc_output_dimensions itk_jpeg12_jpeg_calc_output_dimensions
+#define jpeg_consume_input itk_jpeg12_jpeg_consume_input
+#define jpeg_copy_critical_parameters itk_jpeg12_jpeg_copy_critical_parameters
+#define jpeg_default_colorspace itk_jpeg12_jpeg_default_colorspace
+#define jpeg_destroy itk_jpeg12_jpeg_destroy
+#define jpeg_destroy_compress itk_jpeg12_jpeg_destroy_compress
+#define jpeg_destroy_decompress itk_jpeg12_jpeg_destroy_decompress
+#define jpeg_fdct_float itk_jpeg12_jpeg_fdct_float
+#define jpeg_fdct_ifast itk_jpeg12_jpeg_fdct_ifast
+#define jpeg_fdct_islow itk_jpeg12_jpeg_fdct_islow
+#define jpeg_fill_bit_buffer itk_jpeg12_jpeg_fill_bit_buffer
+#define jpeg_finish_compress itk_jpeg12_jpeg_finish_compress
+#define jpeg_finish_decompress itk_jpeg12_jpeg_finish_decompress
+#define jpeg_finish_output itk_jpeg12_jpeg_finish_output
+#define jpeg_free_large itk_jpeg12_jpeg_free_large
+#define jpeg_free_small itk_jpeg12_jpeg_free_small
+#define jpeg_gen_optimal_table itk_jpeg12_jpeg_gen_optimal_table
+#define jpeg_get_large itk_jpeg12_jpeg_get_large
+#define jpeg_get_small itk_jpeg12_jpeg_get_small
+#define jpeg_has_multiple_scans itk_jpeg12_jpeg_has_multiple_scans
+#define jpeg_huff_decode itk_jpeg12_jpeg_huff_decode
+#define jpeg_idct_1x1 itk_jpeg12_jpeg_idct_1x1
+#define jpeg_idct_2x2 itk_jpeg12_jpeg_idct_2x2
+#define jpeg_idct_4x4 itk_jpeg12_jpeg_idct_4x4
+#define jpeg_idct_float itk_jpeg12_jpeg_idct_float
+#define jpeg_idct_ifast itk_jpeg12_jpeg_idct_ifast
+#define jpeg_idct_islow itk_jpeg12_jpeg_idct_islow
+#define jpeg_input_complete itk_jpeg12_jpeg_input_complete
+#define jpeg_make_c_derived_tbl itk_jpeg12_jpeg_make_c_derived_tbl
+#define jpeg_make_d_derived_tbl itk_jpeg12_jpeg_make_d_derived_tbl
+#define jpeg_mem_available itk_jpeg12_jpeg_mem_available
+#define jpeg_mem_init itk_jpeg12_jpeg_mem_init
+#define jpeg_mem_term itk_jpeg12_jpeg_mem_term
+#define jpeg_natural_order itk_jpeg12_jpeg_natural_order
+#define jpeg_new_colormap itk_jpeg12_jpeg_new_colormap
+#define jpeg_open_backing_store itk_jpeg12_jpeg_open_backing_store
+#define jpeg_quality_scaling itk_jpeg12_jpeg_quality_scaling
+#define jpeg_read_coefficients itk_jpeg12_jpeg_read_coefficients
+#define jpeg_read_header itk_jpeg12_jpeg_read_header
+#define jpeg_read_raw_data itk_jpeg12_jpeg_read_raw_data
+#define jpeg_read_scanlines itk_jpeg12_jpeg_read_scanlines
+#define jpeg_resync_to_restart itk_jpeg12_jpeg_resync_to_restart
+#define jpeg_save_markers itk_jpeg12_jpeg_save_markers
+#define jpeg_set_colorspace itk_jpeg12_jpeg_set_colorspace
+#define jpeg_set_defaults itk_jpeg12_jpeg_set_defaults
+#define jpeg_set_linear_quality itk_jpeg12_jpeg_set_linear_quality
+#define jpeg_set_marker_processor itk_jpeg12_jpeg_set_marker_processor
+#define jpeg_set_quality itk_jpeg12_jpeg_set_quality
+#define jpeg_simple_lossless itk_jpeg12_jpeg_simple_lossless
+#define jpeg_simple_progression itk_jpeg12_jpeg_simple_progression
+#define jpeg_start_compress itk_jpeg12_jpeg_start_compress
+#define jpeg_start_decompress itk_jpeg12_jpeg_start_decompress
+#define jpeg_start_output itk_jpeg12_jpeg_start_output
+#define jpeg_std_error itk_jpeg12_jpeg_std_error
+#define jpeg_std_message_table itk_jpeg12_jpeg_std_message_table
+#define jpeg_stdio_dest itk_jpeg12_jpeg_stdio_dest
+#define jpeg_stdio_src itk_jpeg12_jpeg_stdio_src
+#define jpeg_suppress_tables itk_jpeg12_jpeg_suppress_tables
+#define jpeg_write_coefficients itk_jpeg12_jpeg_write_coefficients
+#define jpeg_write_m_byte itk_jpeg12_jpeg_write_m_byte
+#define jpeg_write_m_header itk_jpeg12_jpeg_write_m_header
+#define jpeg_write_marker itk_jpeg12_jpeg_write_marker
+#define jpeg_write_raw_data itk_jpeg12_jpeg_write_raw_data
+#define jpeg_write_scanlines itk_jpeg12_jpeg_write_scanlines
+#define jpeg_write_tables itk_jpeg12_jpeg_write_tables
+#define jround_up itk_jpeg12_jround_up
+#define jzero_far itk_jpeg12_jzero_far
+
+#endif
diff --git a/Utilities/ITK/Utilities/itkjpeg/mangle_jpeg16bits.h b/Utilities/ITK/Utilities/itkjpeg/mangle_jpeg16bits.h
new file mode 100644
index 0000000000000000000000000000000000000000..a0f1450c8f577ca9a2dfeb27274f729f94284d83
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/mangle_jpeg16bits.h
@@ -0,0 +1,141 @@
+#ifndef itk_jpeg16_mangle_h
+#define itk_jpeg16_mangle_h
+
+/* 
+
+This header file mangles all symbols exported from the jpeg library.
+It is included in all files while building the jpeg library.  Due to
+namespace pollution, no jpeg headers should be included in .h files in
+GDCM. This also allows us to generate three jpeg library (8, 12 and 16bits).
+
+The following command was used to obtain the symbol list:
+
+nm libitkitk_jpeg16.a | grep " [R|T] " | colrm 1 11 | sort
+
+(actually copy/paste from jpeg8bits)
+*/
+
+
+
+#define jcopy_block_row itk_jpeg16_jcopy_block_row
+#define jcopy_sample_rows itk_jpeg16_jcopy_sample_rows
+#define jdiv_round_up itk_jpeg16_jdiv_round_up
+#define jinit_1pass_quantizer itk_jpeg16_jinit_1pass_quantizer
+#define jinit_2pass_quantizer itk_jpeg16_jinit_2pass_quantizer
+#define jinit_arith_decoder itk_jpeg16_jinit_arith_decoder
+#define jinit_arith_encoder itk_jpeg16_jinit_arith_encoder
+#define jinit_c_codec itk_jpeg16_jinit_c_codec
+#define jinit_c_coef_controller itk_jpeg16_jinit_c_coef_controller
+#define jinit_c_diff_controller itk_jpeg16_jinit_c_diff_controller
+#define jinit_c_main_controller itk_jpeg16_jinit_c_main_controller
+#define jinit_c_master_control itk_jpeg16_jinit_c_master_control
+#define jinit_c_prep_controller itk_jpeg16_jinit_c_prep_controller
+#define jinit_c_scaler itk_jpeg16_jinit_c_scaler
+#define jinit_color_converter itk_jpeg16_jinit_color_converter
+#define jinit_color_deconverter itk_jpeg16_jinit_color_deconverter
+#define jinit_compress_master itk_jpeg16_jinit_compress_master
+#define jinit_d_codec itk_jpeg16_jinit_d_codec
+#define jinit_d_coef_controller itk_jpeg16_jinit_d_coef_controller
+#define jinit_d_diff_controller itk_jpeg16_jinit_d_diff_controller
+#define jinit_d_main_controller itk_jpeg16_jinit_d_main_controller
+#define jinit_d_post_controller itk_jpeg16_jinit_d_post_controller
+#define jinit_d_scaler itk_jpeg16_jinit_d_scaler
+#define jinit_differencer itk_jpeg16_jinit_differencer
+#define jinit_downsampler itk_jpeg16_jinit_downsampler
+#define jinit_forward_dct itk_jpeg16_jinit_forward_dct
+#define jinit_input_controller itk_jpeg16_jinit_input_controller
+#define jinit_inverse_dct itk_jpeg16_jinit_inverse_dct
+#define jinit_lhuff_decoder itk_jpeg16_jinit_lhuff_decoder
+#define jinit_lhuff_encoder itk_jpeg16_jinit_lhuff_encoder
+#define jinit_lossless_c_codec itk_jpeg16_jinit_lossless_c_codec
+#define jinit_lossless_d_codec itk_jpeg16_jinit_lossless_d_codec
+#define jinit_lossy_c_codec itk_jpeg16_jinit_lossy_c_codec
+#define jinit_lossy_d_codec itk_jpeg16_jinit_lossy_d_codec
+#define jinit_marker_reader itk_jpeg16_jinit_marker_reader
+#define jinit_marker_writer itk_jpeg16_jinit_marker_writer
+#define jinit_master_decompress itk_jpeg16_jinit_master_decompress
+#define jinit_memory_mgr itk_jpeg16_jinit_memory_mgr
+#define jinit_merged_upsampler itk_jpeg16_jinit_merged_upsampler
+#define jinit_phuff_decoder itk_jpeg16_jinit_phuff_decoder
+#define jinit_phuff_encoder itk_jpeg16_jinit_phuff_encoder
+#define jinit_shuff_decoder itk_jpeg16_jinit_shuff_decoder
+#define jinit_shuff_encoder itk_jpeg16_jinit_shuff_encoder
+#define jinit_undifferencer itk_jpeg16_jinit_undifferencer
+#define jinit_upsampler itk_jpeg16_jinit_upsampler
+#define jpeg_CreateCompress itk_jpeg16_jpeg_CreateCompress
+#define jpeg_CreateDecompress itk_jpeg16_jpeg_CreateDecompress
+#define jpeg_abort itk_jpeg16_jpeg_abort
+#define jpeg_abort_compress itk_jpeg16_jpeg_abort_compress
+#define jpeg_abort_decompress itk_jpeg16_jpeg_abort_decompress
+#define jpeg_add_quant_table itk_jpeg16_jpeg_add_quant_table
+#define jpeg_alloc_huff_table itk_jpeg16_jpeg_alloc_huff_table
+#define jpeg_alloc_quant_table itk_jpeg16_jpeg_alloc_quant_table
+#define jpeg_calc_output_dimensions itk_jpeg16_jpeg_calc_output_dimensions
+#define jpeg_consume_input itk_jpeg16_jpeg_consume_input
+#define jpeg_copy_critical_parameters itk_jpeg16_jpeg_copy_critical_parameters
+#define jpeg_default_colorspace itk_jpeg16_jpeg_default_colorspace
+#define jpeg_destroy itk_jpeg16_jpeg_destroy
+#define jpeg_destroy_compress itk_jpeg16_jpeg_destroy_compress
+#define jpeg_destroy_decompress itk_jpeg16_jpeg_destroy_decompress
+#define jpeg_fdct_float itk_jpeg16_jpeg_fdct_float
+#define jpeg_fdct_ifast itk_jpeg16_jpeg_fdct_ifast
+#define jpeg_fdct_islow itk_jpeg16_jpeg_fdct_islow
+#define jpeg_fill_bit_buffer itk_jpeg16_jpeg_fill_bit_buffer
+#define jpeg_finish_compress itk_jpeg16_jpeg_finish_compress
+#define jpeg_finish_decompress itk_jpeg16_jpeg_finish_decompress
+#define jpeg_finish_output itk_jpeg16_jpeg_finish_output
+#define jpeg_free_large itk_jpeg16_jpeg_free_large
+#define jpeg_free_small itk_jpeg16_jpeg_free_small
+#define jpeg_gen_optimal_table itk_jpeg16_jpeg_gen_optimal_table
+#define jpeg_get_large itk_jpeg16_jpeg_get_large
+#define jpeg_get_small itk_jpeg16_jpeg_get_small
+#define jpeg_has_multiple_scans itk_jpeg16_jpeg_has_multiple_scans
+#define jpeg_huff_decode itk_jpeg16_jpeg_huff_decode
+#define jpeg_idct_1x1 itk_jpeg16_jpeg_idct_1x1
+#define jpeg_idct_2x2 itk_jpeg16_jpeg_idct_2x2
+#define jpeg_idct_4x4 itk_jpeg16_jpeg_idct_4x4
+#define jpeg_idct_float itk_jpeg16_jpeg_idct_float
+#define jpeg_idct_ifast itk_jpeg16_jpeg_idct_ifast
+#define jpeg_idct_islow itk_jpeg16_jpeg_idct_islow
+#define jpeg_input_complete itk_jpeg16_jpeg_input_complete
+#define jpeg_make_c_derived_tbl itk_jpeg16_jpeg_make_c_derived_tbl
+#define jpeg_make_d_derived_tbl itk_jpeg16_jpeg_make_d_derived_tbl
+#define jpeg_mem_available itk_jpeg16_jpeg_mem_available
+#define jpeg_mem_init itk_jpeg16_jpeg_mem_init
+#define jpeg_mem_term itk_jpeg16_jpeg_mem_term
+#define jpeg_natural_order itk_jpeg16_jpeg_natural_order
+#define jpeg_new_colormap itk_jpeg16_jpeg_new_colormap
+#define jpeg_open_backing_store itk_jpeg16_jpeg_open_backing_store
+#define jpeg_quality_scaling itk_jpeg16_jpeg_quality_scaling
+#define jpeg_read_coefficients itk_jpeg16_jpeg_read_coefficients
+#define jpeg_read_header itk_jpeg16_jpeg_read_header
+#define jpeg_read_raw_data itk_jpeg16_jpeg_read_raw_data
+#define jpeg_read_scanlines itk_jpeg16_jpeg_read_scanlines
+#define jpeg_resync_to_restart itk_jpeg16_jpeg_resync_to_restart
+#define jpeg_save_markers itk_jpeg16_jpeg_save_markers
+#define jpeg_set_colorspace itk_jpeg16_jpeg_set_colorspace
+#define jpeg_set_defaults itk_jpeg16_jpeg_set_defaults
+#define jpeg_set_linear_quality itk_jpeg16_jpeg_set_linear_quality
+#define jpeg_set_marker_processor itk_jpeg16_jpeg_set_marker_processor
+#define jpeg_set_quality itk_jpeg16_jpeg_set_quality
+#define jpeg_simple_lossless itk_jpeg16_jpeg_simple_lossless
+#define jpeg_simple_progression itk_jpeg16_jpeg_simple_progression
+#define jpeg_start_compress itk_jpeg16_jpeg_start_compress
+#define jpeg_start_decompress itk_jpeg16_jpeg_start_decompress
+#define jpeg_start_output itk_jpeg16_jpeg_start_output
+#define jpeg_std_error itk_jpeg16_jpeg_std_error
+#define jpeg_std_message_table itk_jpeg16_jpeg_std_message_table
+#define jpeg_stdio_dest itk_jpeg16_jpeg_stdio_dest
+#define jpeg_stdio_src itk_jpeg16_jpeg_stdio_src
+#define jpeg_suppress_tables itk_jpeg16_jpeg_suppress_tables
+#define jpeg_write_coefficients itk_jpeg16_jpeg_write_coefficients
+#define jpeg_write_m_byte itk_jpeg16_jpeg_write_m_byte
+#define jpeg_write_m_header itk_jpeg16_jpeg_write_m_header
+#define jpeg_write_marker itk_jpeg16_jpeg_write_marker
+#define jpeg_write_raw_data itk_jpeg16_jpeg_write_raw_data
+#define jpeg_write_scanlines itk_jpeg16_jpeg_write_scanlines
+#define jpeg_write_tables itk_jpeg16_jpeg_write_tables
+#define jround_up itk_jpeg16_jround_up
+#define jzero_far itk_jpeg16_jzero_far
+
+#endif
diff --git a/Utilities/ITK/Utilities/itkjpeg/mangle_jpeg8bits.h b/Utilities/ITK/Utilities/itkjpeg/mangle_jpeg8bits.h
new file mode 100644
index 0000000000000000000000000000000000000000..226aa54b904fa6443cc960ade8541da6f8a119b2
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/mangle_jpeg8bits.h
@@ -0,0 +1,139 @@
+#ifndef itk_jpeg8_mangle_h
+#define itk_jpeg8_mangle_h
+
+/* 
+
+This header file mangles all symbols exported from the jpeg library.
+It is included in all files while building the jpeg library.  Due to
+namespace pollution, no jpeg headers should be included in .h files in
+GDCM. This also allows us to generate two jpeg library (8bits and 12bits).
+
+The following command was used to obtain the symbol list:
+
+nm libitkitk_jpeg8.a | grep " [R|T] " | colrm 1 11 | sort
+*/
+
+
+#define jcopy_block_row itk_jpeg8_jcopy_block_row
+#define jcopy_sample_rows itk_jpeg8_jcopy_sample_rows
+#define jdiv_round_up itk_jpeg8_jdiv_round_up
+#define jinit_1pass_quantizer itk_jpeg8_jinit_1pass_quantizer
+#define jinit_2pass_quantizer itk_jpeg8_jinit_2pass_quantizer
+#define jinit_arith_decoder itk_jpeg8_jinit_arith_decoder
+#define jinit_arith_encoder itk_jpeg8_jinit_arith_encoder
+#define jinit_c_codec itk_jpeg8_jinit_c_codec
+#define jinit_c_coef_controller itk_jpeg8_jinit_c_coef_controller
+#define jinit_c_diff_controller itk_jpeg8_jinit_c_diff_controller
+#define jinit_c_main_controller itk_jpeg8_jinit_c_main_controller
+#define jinit_c_master_control itk_jpeg8_jinit_c_master_control
+#define jinit_c_prep_controller itk_jpeg8_jinit_c_prep_controller
+#define jinit_c_scaler itk_jpeg8_jinit_c_scaler
+#define jinit_color_converter itk_jpeg8_jinit_color_converter
+#define jinit_color_deconverter itk_jpeg8_jinit_color_deconverter
+#define jinit_compress_master itk_jpeg8_jinit_compress_master
+#define jinit_d_codec itk_jpeg8_jinit_d_codec
+#define jinit_d_coef_controller itk_jpeg8_jinit_d_coef_controller
+#define jinit_d_diff_controller itk_jpeg8_jinit_d_diff_controller
+#define jinit_d_main_controller itk_jpeg8_jinit_d_main_controller
+#define jinit_d_post_controller itk_jpeg8_jinit_d_post_controller
+#define jinit_d_scaler itk_jpeg8_jinit_d_scaler
+#define jinit_differencer itk_jpeg8_jinit_differencer
+#define jinit_downsampler itk_jpeg8_jinit_downsampler
+#define jinit_forward_dct itk_jpeg8_jinit_forward_dct
+#define jinit_input_controller itk_jpeg8_jinit_input_controller
+#define jinit_inverse_dct itk_jpeg8_jinit_inverse_dct
+#define jinit_lhuff_decoder itk_jpeg8_jinit_lhuff_decoder
+#define jinit_lhuff_encoder itk_jpeg8_jinit_lhuff_encoder
+#define jinit_lossless_c_codec itk_jpeg8_jinit_lossless_c_codec
+#define jinit_lossless_d_codec itk_jpeg8_jinit_lossless_d_codec
+#define jinit_lossy_c_codec itk_jpeg8_jinit_lossy_c_codec
+#define jinit_lossy_d_codec itk_jpeg8_jinit_lossy_d_codec
+#define jinit_marker_reader itk_jpeg8_jinit_marker_reader
+#define jinit_marker_writer itk_jpeg8_jinit_marker_writer
+#define jinit_master_decompress itk_jpeg8_jinit_master_decompress
+#define jinit_memory_mgr itk_jpeg8_jinit_memory_mgr
+#define jinit_merged_upsampler itk_jpeg8_jinit_merged_upsampler
+#define jinit_phuff_decoder itk_jpeg8_jinit_phuff_decoder
+#define jinit_phuff_encoder itk_jpeg8_jinit_phuff_encoder
+#define jinit_shuff_decoder itk_jpeg8_jinit_shuff_decoder
+#define jinit_shuff_encoder itk_jpeg8_jinit_shuff_encoder
+#define jinit_undifferencer itk_jpeg8_jinit_undifferencer
+#define jinit_upsampler itk_jpeg8_jinit_upsampler
+#define jpeg_CreateCompress itk_jpeg8_jpeg_CreateCompress
+#define jpeg_CreateDecompress itk_jpeg8_jpeg_CreateDecompress
+#define jpeg_abort itk_jpeg8_jpeg_abort
+#define jpeg_abort_compress itk_jpeg8_jpeg_abort_compress
+#define jpeg_abort_decompress itk_jpeg8_jpeg_abort_decompress
+#define jpeg_add_quant_table itk_jpeg8_jpeg_add_quant_table
+#define jpeg_alloc_huff_table itk_jpeg8_jpeg_alloc_huff_table
+#define jpeg_alloc_quant_table itk_jpeg8_jpeg_alloc_quant_table
+#define jpeg_calc_output_dimensions itk_jpeg8_jpeg_calc_output_dimensions
+#define jpeg_consume_input itk_jpeg8_jpeg_consume_input
+#define jpeg_copy_critical_parameters itk_jpeg8_jpeg_copy_critical_parameters
+#define jpeg_default_colorspace itk_jpeg8_jpeg_default_colorspace
+#define jpeg_destroy itk_jpeg8_jpeg_destroy
+#define jpeg_destroy_compress itk_jpeg8_jpeg_destroy_compress
+#define jpeg_destroy_decompress itk_jpeg8_jpeg_destroy_decompress
+#define jpeg_fdct_float itk_jpeg8_jpeg_fdct_float
+#define jpeg_fdct_ifast itk_jpeg8_jpeg_fdct_ifast
+#define jpeg_fdct_islow itk_jpeg8_jpeg_fdct_islow
+#define jpeg_fill_bit_buffer itk_jpeg8_jpeg_fill_bit_buffer
+#define jpeg_finish_compress itk_jpeg8_jpeg_finish_compress
+#define jpeg_finish_decompress itk_jpeg8_jpeg_finish_decompress
+#define jpeg_finish_output itk_jpeg8_jpeg_finish_output
+#define jpeg_free_large itk_jpeg8_jpeg_free_large
+#define jpeg_free_small itk_jpeg8_jpeg_free_small
+#define jpeg_gen_optimal_table itk_jpeg8_jpeg_gen_optimal_table
+#define jpeg_get_large itk_jpeg8_jpeg_get_large
+#define jpeg_get_small itk_jpeg8_jpeg_get_small
+#define jpeg_has_multiple_scans itk_jpeg8_jpeg_has_multiple_scans
+#define jpeg_huff_decode itk_jpeg8_jpeg_huff_decode
+#define jpeg_idct_1x1 itk_jpeg8_jpeg_idct_1x1
+#define jpeg_idct_2x2 itk_jpeg8_jpeg_idct_2x2
+#define jpeg_idct_4x4 itk_jpeg8_jpeg_idct_4x4
+#define jpeg_idct_float itk_jpeg8_jpeg_idct_float
+#define jpeg_idct_ifast itk_jpeg8_jpeg_idct_ifast
+#define jpeg_idct_islow itk_jpeg8_jpeg_idct_islow
+#define jpeg_input_complete itk_jpeg8_jpeg_input_complete
+#define jpeg_make_c_derived_tbl itk_jpeg8_jpeg_make_c_derived_tbl
+#define jpeg_make_d_derived_tbl itk_jpeg8_jpeg_make_d_derived_tbl
+#define jpeg_mem_available itk_jpeg8_jpeg_mem_available
+#define jpeg_mem_init itk_jpeg8_jpeg_mem_init
+#define jpeg_mem_term itk_jpeg8_jpeg_mem_term
+#define jpeg_natural_order itk_jpeg8_jpeg_natural_order
+#define jpeg_new_colormap itk_jpeg8_jpeg_new_colormap
+#define jpeg_open_backing_store itk_jpeg8_jpeg_open_backing_store
+#define jpeg_quality_scaling itk_jpeg8_jpeg_quality_scaling
+#define jpeg_read_coefficients itk_jpeg8_jpeg_read_coefficients
+#define jpeg_read_header itk_jpeg8_jpeg_read_header
+#define jpeg_read_raw_data itk_jpeg8_jpeg_read_raw_data
+#define jpeg_read_scanlines itk_jpeg8_jpeg_read_scanlines
+#define jpeg_resync_to_restart itk_jpeg8_jpeg_resync_to_restart
+#define jpeg_save_markers itk_jpeg8_jpeg_save_markers
+#define jpeg_set_colorspace itk_jpeg8_jpeg_set_colorspace
+#define jpeg_set_defaults itk_jpeg8_jpeg_set_defaults
+#define jpeg_set_linear_quality itk_jpeg8_jpeg_set_linear_quality
+#define jpeg_set_marker_processor itk_jpeg8_jpeg_set_marker_processor
+#define jpeg_set_quality itk_jpeg8_jpeg_set_quality
+#define jpeg_simple_lossless itk_jpeg8_jpeg_simple_lossless
+#define jpeg_simple_progression itk_jpeg8_jpeg_simple_progression
+#define jpeg_start_compress itk_jpeg8_jpeg_start_compress
+#define jpeg_start_decompress itk_jpeg8_jpeg_start_decompress
+#define jpeg_start_output itk_jpeg8_jpeg_start_output
+#define jpeg_std_error itk_jpeg8_jpeg_std_error
+#define jpeg_std_message_table itk_jpeg8_jpeg_std_message_table
+#define jpeg_stdio_dest itk_jpeg8_jpeg_stdio_dest
+#define jpeg_stdio_src itk_jpeg8_jpeg_stdio_src
+#define jpeg_suppress_tables itk_jpeg8_jpeg_suppress_tables
+#define jpeg_write_coefficients itk_jpeg8_jpeg_write_coefficients
+#define jpeg_write_m_byte itk_jpeg8_jpeg_write_m_byte
+#define jpeg_write_m_header itk_jpeg8_jpeg_write_m_header
+#define jpeg_write_marker itk_jpeg8_jpeg_write_marker
+#define jpeg_write_raw_data itk_jpeg8_jpeg_write_raw_data
+#define jpeg_write_scanlines itk_jpeg8_jpeg_write_scanlines
+#define jpeg_write_tables itk_jpeg8_jpeg_write_tables
+#define jround_up itk_jpeg8_jround_up
+#define jzero_far itk_jpeg8_jzero_far
+
+
+#endif
diff --git a/Utilities/ITK/Utilities/itkjpeg/structure.doc b/Utilities/ITK/Utilities/itkjpeg/structure.doc
new file mode 100644
index 0000000000000000000000000000000000000000..3d62accff5442de5a39ac56c45da3c361d757aa7
--- /dev/null
+++ b/Utilities/ITK/Utilities/itkjpeg/structure.doc
@@ -0,0 +1,1042 @@
+IJG JPEG LIBRARY:  SYSTEM ARCHITECTURE
+
+Copyright (C) 1991-1995, Thomas G. Lane.
+This file is part of the Independent JPEG Group's software.
+For conditions of distribution and use, see the accompanying README file.
+
+
+This file provides an overview of the architecture of the IJG JPEG software;
+that is, the functions of the various modules in the system and the interfaces
+between modules.  For more precise details about any data structure or calling
+convention, see the include files and comments in the source code.
+
+We assume that the reader is already somewhat familiar with the JPEG standard.
+The README file includes references for learning about JPEG.  The file
+libjpeg.doc describes the library from the viewpoint of an application
+programmer using the library; it's best to read that file before this one.
+Also, the file coderules.doc describes the coding style conventions we use.
+
+In this document, JPEG-specific terminology follows the JPEG standard:
+  A "component" means a color channel, e.g., Red or Luminance.
+  A "sample" is a single component value (i.e., one number in the image data).
+  A "coefficient" is a frequency coefficient (a DCT transform output number).
+  A "block" is an 8x8 group of samples or coefficients.
+  A "data unit" is an abstract data type which is either a block for lossy
+	(DCT-based) codecs or a sample for lossless (predictive) codecs.
+  An "MCU" (minimum coded unit) is an interleaved set of data units of size
+	determined by the sampling factors, or a single data unit in a
+	noninterleaved scan.
+We do not use the terms "pixel" and "sample" interchangeably.  When we say
+pixel, we mean an element of the full-size image, while a sample is an element
+of the downsampled image.  Thus the number of samples may vary across
+components while the number of pixels does not.  (This terminology is not used
+rigorously throughout the code, but it is used in places where confusion would
+otherwise result.)
+
+
+*** System features ***
+
+The IJG distribution contains two parts:
+  * A subroutine library for JPEG compression and decompression.
+  * cjpeg/djpeg, two sample applications that use the library to transform
+    JFIF JPEG files to and from several other image formats.
+cjpeg/djpeg are of no great intellectual complexity: they merely add a simple
+command-line user interface and I/O routines for several uncompressed image
+formats.  This document concentrates on the library itself.
+
+We desire the library to be capable of supporting all JPEG baseline, extended
+sequential, and progressive DCT processes, as well as the lossless (spatial)
+process.  Hierarchical processes are not supported.
+
+Within these limits, any set of compression parameters allowed by the JPEG
+spec should be readable for decompression.  (We can be more restrictive about
+what formats we can generate.)  Although the system design allows for all
+parameter values, some uncommon settings are not yet implemented and may
+never be; nonintegral sampling ratios are the prime example.  Furthermore,
+we treat 8-bit vs. 12-bit data precision as a compile-time switch, not a
+run-time option, because most machines can store 8-bit pixels much more
+compactly than 12-bit.
+
+For legal reasons, JPEG arithmetic coding is not currently supported, but
+extending the library to include it would be straightforward.
+
+By itself, the library handles only interchange JPEG datastreams --- in
+particular the widely used JFIF file format.  The library can be used by
+surrounding code to process interchange or abbreviated JPEG datastreams that
+are embedded in more complex file formats.  (For example, libtiff uses this
+library to implement JPEG compression within the TIFF file format.)
+
+The library includes a substantial amount of code that is not covered by the
+JPEG standard but is necessary for typical applications of JPEG.  These
+functions preprocess the image before JPEG compression or postprocess it after
+decompression.  They include colorspace conversion, downsampling/upsampling,
+and color quantization.  This code can be omitted if not needed.
+
+A wide range of quality vs. speed tradeoffs are possible in JPEG processing,
+and even more so in decompression postprocessing.  The decompression library
+provides multiple implementations that cover most of the useful tradeoffs,
+ranging from very-high-quality down to fast-preview operation.  On the
+compression side we have generally not provided low-quality choices, since
+compression is normally less time-critical.  It should be understood that the
+low-quality modes may not meet the JPEG standard's accuracy requirements;
+nonetheless, they are useful for viewers.
+
+
+*** Portability issues ***
+
+Portability is an essential requirement for the library.  The key portability
+issues that show up at the level of system architecture are:
+
+1.  Memory usage.  We want the code to be able to run on PC-class machines
+with limited memory.  Images should therefore be processed sequentially (in
+strips), to avoid holding the whole image in memory at once.  Where a
+full-image buffer is necessary, we should be able to use either virtual memory
+or temporary files.
+
+2.  Near/far pointer distinction.  To run efficiently on 80x86 machines, the
+code should distinguish "small" objects (kept in near data space) from
+"large" ones (kept in far data space).  This is an annoying restriction, but
+fortunately it does not impact code quality for less brain-damaged machines,
+and the source code clutter turns out to be minimal with sufficient use of
+pointer typedefs.
+
+3. Data precision.  We assume that "char" is at least 8 bits, "short" and
+"int" at least 16, "long" at least 32.  The code will work fine with larger
+data sizes, although memory may be used inefficiently in some cases.  However,
+the JPEG compressed datastream must ultimately appear on external storage as a
+sequence of 8-bit bytes if it is to conform to the standard.  This may pose a
+problem on machines where char is wider than 8 bits.  The library represents
+compressed data as an array of values of typedef JOCTET.  If no data type
+exactly 8 bits wide is available, custom data source and data destination
+modules must be written to unpack and pack the chosen JOCTET datatype into
+8-bit external representation.
+
+
+*** System overview ***
+
+The compressor and decompressor are each divided into two main sections:
+the JPEG compressor or decompressor proper, and the preprocessing or
+postprocessing functions.  The interface between these two sections is the
+image data that the official JPEG spec regards as its input or output: this
+data is in the colorspace to be used for compression, and it is downsampled
+to the sampling factors to be used.  The preprocessing and postprocessing
+steps are responsible for converting a normal image representation to or from
+this form.  (Those few applications that want to deal with YCbCr downsampled
+data can skip the preprocessing or postprocessing step.)
+
+Looking more closely, the compressor library contains the following main
+elements:
+
+  Preprocessing:
+    * Color space conversion (e.g., RGB to YCbCr).
+    * Edge expansion and downsampling.  Optionally, this step can do simple
+      smoothing --- this is often helpful for low-quality source data.
+  Lossy JPEG proper:
+    * MCU assembly, DCT, quantization.
+    * Entropy coding (sequential or progressive, Huffman or arithmetic).
+  Lossless JPEG proper:
+    * Point transform.
+    * Prediction, differencing.
+    * Entropy coding (Huffman or arithmetic)
+
+In addition to these modules we need overall control, marker generation,
+and support code (memory management & error handling).  There is also a
+module responsible for physically writing the output data --- typically
+this is just an interface to fwrite(), but some applications may need to
+do something else with the data.
+
+The decompressor library contains the following main elements:
+
+  Lossy JPEG proper:
+    * Entropy decoding (sequential or progressive, Huffman or arithmetic).
+    * Dequantization, inverse DCT, MCU disassembly.
+  Lossless JPEG proper:
+    * Entropy decoding (Huffman or arithmetic).
+    * Prediction, undifferencing.
+    * Point transform, sample size scaling.
+  Postprocessing:
+    * Upsampling.  Optionally, this step may be able to do more general
+      rescaling of the image.
+    * Color space conversion (e.g., YCbCr to RGB).  This step may also
+      provide gamma adjustment [ currently it does not ].
+    * Optional color quantization (e.g., reduction to 256 colors).
+    * Optional color precision reduction (e.g., 24-bit to 15-bit color).
+      [This feature is not currently implemented.]
+
+We also need overall control, marker parsing, and a data source module.
+The support code (memory management & error handling) can be shared with
+the compression half of the library.
+
+There may be several implementations of each of these elements, particularly
+in the decompressor, where a wide range of speed/quality tradeoffs is very
+useful.  It must be understood that some of the best speedups involve
+merging adjacent steps in the pipeline.  For example, upsampling, color space
+conversion, and color quantization might all be done at once when using a
+low-quality ordered-dither technique.  The system architecture is designed to
+allow such merging where appropriate.
+
+
+Note: it is convenient to regard edge expansion (padding to block boundaries)
+as a preprocessing/postprocessing function, even though the JPEG spec includes
+it in compression/decompression.  We do this because downsampling/upsampling
+can be simplified a little if they work on padded data: it's not necessary to
+have special cases at the right and bottom edges.  Therefore the interface
+buffer is always an integral number of blocks wide and high, and we expect
+compression preprocessing to pad the source data properly.  Padding will occur
+only to the next block (8-sample) boundary.  In an interleaved-scan situation,
+additional dummy blocks may be used to fill out MCUs, but the MCU assembly and
+disassembly logic will create or discard these blocks internally.  (This is
+advantageous for speed reasons, since we avoid DCTing the dummy blocks.
+It also permits a small reduction in file size, because the compressor can
+choose dummy block contents so as to minimize their size in compressed form.
+Finally, it makes the interface buffer specification independent of whether
+the file is actually interleaved or not.)  Applications that wish to deal
+directly with the downsampled data must provide similar buffering and padding
+for odd-sized images.
+
+
+*** Poor man's object-oriented programming ***
+
+It should be clear by now that we have a lot of quasi-independent processing
+steps, many of which have several possible behaviors.  To avoid cluttering the
+code with lots of switch statements, we use a simple form of object-style
+programming to separate out the different possibilities.
+
+For example, two different color quantization algorithms could be implemented
+as two separate modules that present the same external interface; at runtime,
+the calling code will access the proper module indirectly through an "object".
+
+We can get the limited features we need while staying within portable C.
+The basic tool is a function pointer.  An "object" is just a struct
+containing one or more function pointer fields, each of which corresponds to
+a method name in real object-oriented languages.  During initialization we
+fill in the function pointers with references to whichever module we have
+determined we need to use in this run.  Then invocation of the module is done
+by indirecting through a function pointer; on most machines this is no more
+expensive than a switch statement, which would be the only other way of
+making the required run-time choice.  The really significant benefit, of
+course, is keeping the source code clean and well structured.
+
+We can also arrange to have private storage that varies between different
+implementations of the same kind of object.  We do this by making all the
+module-specific object structs be separately allocated entities, which will
+be accessed via pointers in the master compression or decompression struct.
+The "public" fields or methods for a given kind of object are specified by
+a commonly known struct.  But a module's initialization code can allocate
+a larger struct that contains the common struct as its first member, plus
+additional private fields.  With appropriate pointer casting, the module's
+internal functions can access these private fields.  (For a simple example,
+see jdatadst.c, which implements the external interface specified by struct
+jpeg_destination_mgr, but adds extra fields.)
+
+(Of course this would all be a lot easier if we were using C++, but we are
+not yet prepared to assume that everyone has a C++ compiler.)
+
+An important benefit of this scheme is that it is easy to provide multiple
+versions of any method, each tuned to a particular case.  While a lot of
+precalculation might be done to select an optimal implementation of a method,
+the cost per invocation is constant.  For example, the upsampling step might
+have a "generic" method, plus one or more "hardwired" methods for the most
+popular sampling factors; the hardwired methods would be faster because they'd
+use straight-line code instead of for-loops.  The cost to determine which
+method to use is paid only once, at startup, and the selection criteria are
+hidden from the callers of the method.
+
+This plan differs a little bit from usual object-oriented structures, in that
+only one instance of each object class will exist during execution.  The
+reason for having the class structure is that on different runs we may create
+different instances (choose to execute different modules).  You can think of
+the term "method" as denoting the common interface presented by a particular
+set of interchangeable functions, and "object" as denoting a group of related
+methods, or the total shared interface behavior of a group of modules.
+
+
+*** Overall control structure ***
+
+We previously mentioned the need for overall control logic in the compression
+and decompression libraries.  In IJG implementations prior to v5, overall
+control was mostly provided by "pipeline control" modules, which proved to be
+large, unwieldy, and hard to understand.  To improve the situation, the
+control logic has been subdivided into multiple modules.  The control modules
+consist of:
+
+1. Master control for module selection and initialization.  This has two
+responsibilities:
+
+   1A.  Startup initialization at the beginning of image processing.
+        The individual processing modules to be used in this run are selected
+        and given initialization calls.
+
+   1B.  Per-pass control.  This determines how many passes will be performed
+        and calls each active processing module to configure itself
+        appropriately at the beginning of each pass.  End-of-pass processing,
+	where necessary, is also invoked from the master control module.
+
+   Method selection is partially distributed, in that a particular processing
+   module may contain several possible implementations of a particular method,
+   which it will select among when given its initialization call.  The master
+   control code need only be concerned with decisions that affect more than
+   one module.
+ 
+2. Data buffering control.  A separate control module exists for each
+   inter-processing-step data buffer.  This module is responsible for
+   invoking the processing steps that write or read that data buffer.
+
+Each buffer controller sees the world as follows:
+
+input data => processing step A => buffer => processing step B => output data
+                      |              |               |
+              ------------------ controller ------------------
+
+The controller knows the dataflow requirements of steps A and B: how much data
+they want to accept in one chunk and how much they output in one chunk.  Its
+function is to manage its buffer and call A and B at the proper times.
+
+A data buffer control module may itself be viewed as a processing step by a
+higher-level control module; thus the control modules form a binary tree with
+elementary processing steps at the leaves of the tree.
+
+The control modules are objects.  A considerable amount of flexibility can
+be had by replacing implementations of a control module.  For example:
+* Merging of adjacent steps in the pipeline is done by replacing a control
+  module and its pair of processing-step modules with a single processing-
+  step module.  (Hence the possible merges are determined by the tree of
+  control modules.)
+* In some processing modes, a given interstep buffer need only be a "strip"
+  buffer large enough to accommodate the desired data chunk sizes.  In other
+  modes, a full-image buffer is needed and several passes are required.
+  The control module determines which kind of buffer is used and manipulates
+  virtual array buffers as needed.  One or both processing steps may be
+  unaware of the multi-pass behavior.
+
+In theory, we might be able to make all of the data buffer controllers
+interchangeable and provide just one set of implementations for all.  In
+practice, each one contains considerable special-case processing for its
+particular job.  The buffer controller concept should be regarded as an
+overall system structuring principle, not as a complete description of the
+task performed by any one controller.
+
+
+*** Codec object structure ***
+
+As noted above, this library supports both the lossy (DCT-based) and lossless
+JPEG processes.  Because these processes have little in common with one another
+(and their implementations share very little code), we need to provide a way to
+isloate the underlying JPEG process from the rest of the library.  This is
+accomplished by introducing an abstract "codec object" which acts a generic
+interface to the JPEG (de)compressor proper.  
+
+Using the power of the object-oriented scheme described above, we build the
+lossy and lossless modules as two separate implementations of the codec object.
+Switching between lossy and lossless processes then becomes as trivial as
+assigning the appropriate method pointers during initialization of the library.
+
+
+*** Compression object structure ***
+
+Here is a sketch of the logical structure of the JPEG compression library:
+
+                                                 |-- Colorspace conversion
+                  |-- Preprocessing controller --|
+                  |                              |-- Downsampling
+                  |
+Main controller --|
+                  |                       /--> Lossy codec
+                  |                      /
+                  |-- Compression codec <          *OR*
+                                         \
+                                          \--> Lossless codec
+
+
+where the lossy codec looks like:
+
+                             |-- Forward DCT, quantize
+<-- Coefficient controller --|
+                             |-- Entropy encoding
+
+
+and the lossless codec looks like:
+
+                            |-- Point transformation
+                            |
+<-- Difference controller --|-- Prediction, differencing
+                            |
+                            |-- Lossless entropy encoding
+
+
+This sketch also describes the flow of control (subroutine calls) during
+typical image data processing.  Each of the components shown in the diagram is
+an "object" which may have several different implementations available.  One
+or more source code files contain the actual implementation(s) of each object.
+
+The objects shown above are:
+
+* Main controller: buffer controller for the subsampled-data buffer, which
+  holds the preprocessed input data.  This controller invokes preprocessing to
+  fill the subsampled-data buffer, and JPEG compression to empty it.  There is
+  usually no need for a full-image buffer here; a strip buffer is adequate.
+
+* Preprocessing controller: buffer controller for the downsampling input data
+  buffer, which lies between colorspace conversion and downsampling.  Note
+  that a unified conversion/downsampling module would probably replace this
+  controller entirely.
+
+* Colorspace conversion: converts application image data into the desired
+  JPEG color space; also changes the data from pixel-interleaved layout to
+  separate component planes.  Processes one pixel row at a time.
+
+* Downsampling: performs reduction of chroma components as required.
+  Optionally may perform pixel-level smoothing as well.  Processes a "row
+  group" at a time, where a row group is defined as Vmax pixel rows of each
+  component before downsampling, and Vk sample rows afterwards (remember Vk
+  differs across components).  Some downsampling or smoothing algorithms may
+  require context rows above and below the current row group; the
+  preprocessing controller is responsible for supplying these rows via proper
+  buffering.  The downsampler is responsible for edge expansion at the right
+  edge (i.e., extending each sample row to a multiple of 8 samples); but the
+  preprocessing controller is responsible for vertical edge expansion (i.e.,
+  duplicating the bottom sample row as needed to make a multiple of 8 rows).
+
+* Coefficient controller: buffer controller for the DCT-coefficient data.
+  This controller handles MCU assembly, including insertion of dummy DCT
+  blocks when needed at the right or bottom edge.  When performing
+  Huffman-code optimization or emitting a multiscan JPEG file, this
+  controller is responsible for buffering the full image.  The equivalent of
+  one fully interleaved MCU row of subsampled data is processed per call,
+  even when the JPEG file is noninterleaved.
+
+* Forward DCT and quantization: Perform DCT, quantize, and emit coefficients.
+  Works on one or more DCT blocks at a time.  (Note: the coefficients are now
+  emitted in normal array order, which the entropy encoder is expected to
+  convert to zigzag order as necessary.  Prior versions of the IJG code did
+  the conversion to zigzag order within the quantization step.)
+
+* Entropy encoding: Perform Huffman or arithmetic entropy coding and emit the
+  coded data to the data destination module.  Works on one MCU per call.
+  For progressive JPEG, the same DCT blocks are fed to the entropy coder
+  during each pass, and the coder must emit the appropriate subset of
+  coefficients.
+
+* Difference controller: buffer controller for the spatial difference data.
+  When emitting a multiscan JPEG file, this controller is responsible for
+  buffering the full image.  The equivalent of one fully interleaved MCU row
+  of subsampled data is processed per call, even when the JPEG file is
+  noninterleaved.
+
+* Point transformation: Scale the data down by the point transformation
+  parameter.
+
+* Prediction and differencing: Calculate the predictor and subtract it
+  from the input.  Works on one scanline per call.  The difference
+  controller supplies the prior scanline which is used for prediction.
+
+* Lossless entropy encoding: Perform Huffman or arithmetic entropy coding and
+  emit the coded data to the data destination module.  This module handles MCU
+  assembly.  Works on one MCU-row per call.
+
+In addition to the above objects, the compression library includes these
+objects:
+
+* Master control: determines the number of passes required, controls overall
+  and per-pass initialization of the other modules.
+
+* Marker writing: generates JPEG markers (except for RSTn, which is emitted
+  by the entropy encoder when needed).
+
+* Data destination manager: writes the output JPEG datastream to its final
+  destination (e.g., a file).  The destination manager supplied with the
+  library knows how to write to a stdio stream; for other behaviors, the
+  surrounding application may provide its own destination manager.
+
+* Memory manager: allocates and releases memory, controls virtual arrays
+  (with backing store management, where required).
+
+* Error handler: performs formatting and output of error and trace messages;
+  determines handling of nonfatal errors.  The surrounding application may
+  override some or all of this object's methods to change error handling.
+
+* Progress monitor: supports output of "percent-done" progress reports.
+  This object represents an optional callback to the surrounding application:
+  if wanted, it must be supplied by the application.
+
+The error handler, destination manager, and progress monitor objects are
+defined as separate objects in order to simplify application-specific
+customization of the JPEG library.  A surrounding application may override
+individual methods or supply its own all-new implementation of one of these
+objects.  The object interfaces for these objects are therefore treated as
+part of the application interface of the library, whereas the other objects
+are internal to the library.
+
+The error handler and memory manager are shared by JPEG compression and
+decompression; the progress monitor, if used, may be shared as well.
+
+
+*** Decompression object structure ***
+
+Here is a sketch of the logical structure of the JPEG decompression library:
+
+                                            /--> Lossy codec
+                                           /
+                  |-- Decompression codec <          *OR*
+                  |                        \
+                  |                         \--> Lossless codec
+Main controller --|
+                  |
+                  |                               |-- Upsampling
+                  |-- Postprocessing controller --|   |-- Colorspace conversion
+                                                  |-- Color quantization
+                                                  |-- Color precision reduction
+
+
+where the lossy codec looks like:
+
+                             |-- Entropy decoding
+<-- Coefficient controller --|
+                             |-- Dequantize, Inverse DCT
+
+
+and the lossless codec looks like:
+
+                            |-- Lossless entropy decoding
+                            |
+<-- Difference controller --|-- Prediction, undifferencing
+                            |
+                            |-- Point transformation, sample size scaling
+
+
+As before, this diagram also represents typical control flow.  The objects
+shown are:
+
+* Main controller: buffer controller for the subsampled-data buffer, which
+  holds the output of JPEG decompression proper.  This controller's primary
+  task is to feed the postprocessing procedure.  Some upsampling algorithms
+  may require context rows above and below the current row group; when this
+  is true, the main controller is responsible for managing its buffer so as
+  to make context rows available.  In the current design, the main buffer is
+  always a strip buffer; a full-image buffer is never required.
+
+* Coefficient controller: buffer controller for the DCT-coefficient data.
+  This controller handles MCU disassembly, including deletion of any dummy
+  DCT blocks at the right or bottom edge.  When reading a multiscan JPEG
+  file, this controller is responsible for buffering the full image.
+  (Buffering DCT coefficients, rather than samples, is necessary to support
+  progressive JPEG.)  The equivalent of one fully interleaved MCU row of
+  subsampled data is processed per call, even when the source JPEG file is
+  noninterleaved.
+
+* Entropy decoding: Read coded data from the data source module and perform
+  Huffman or arithmetic entropy decoding.  Works on one MCU per call.
+  For progressive JPEG decoding, the coefficient controller supplies the prior
+  coefficients of each MCU (initially all zeroes), which the entropy decoder
+  modifies in each scan.
+
+* Dequantization and inverse DCT: like it says.  Note that the coefficients
+  buffered by the coefficient controller have NOT been dequantized; we
+  merge dequantization and inverse DCT into a single step for speed reasons.
+  When scaled-down output is asked for, simplified DCT algorithms may be used
+  that emit only 1x1, 2x2, or 4x4 samples per DCT block, not the full 8x8.
+  Works on one DCT block at a time.
+
+* Difference controller: buffer controller for the spatial difference data.
+  When reading a multiscan JPEG file, this controller is responsible for
+  buffering the full image. The equivalent of one fully interleaved MCU row
+  is processed per call, even when the source JPEG file is noninterleaved.
+
+* Lossless entropy decoding: Read coded data from the data source module and
+  perform Huffman or arithmetic entropy decoding.  Works on one MCU-row per
+  call.
+
+* Prediction and undifferencing: Calculate the predictor and add it to the
+  decoded difference.  Works on one scanline per call.  The difference
+  controller supplies the prior scanline which is used for prediction.
+
+* Point transform and sample size scaling: Scale the data up by the point
+  transformation parameter and scale it down to fit into the compiled-in
+  sample size.
+
+* Postprocessing controller: buffer controller for the color quantization
+  input buffer, when quantization is in use.  (Without quantization, this
+  controller just calls the upsampler.)  For two-pass quantization, this
+  controller is responsible for buffering the full-image data.
+
+* Upsampling: restores chroma components to full size.  (May support more
+  general output rescaling, too.  Note that if undersized DCT outputs have
+  been emitted by the DCT module, this module must adjust so that properly
+  sized outputs are created.)  Works on one row group at a time.  This module
+  also calls the color conversion module, so its top level is effectively a
+  buffer controller for the upsampling->color conversion buffer.  However, in
+  all but the highest-quality operating modes, upsampling and color
+  conversion are likely to be merged into a single step.
+
+* Colorspace conversion: convert from JPEG color space to output color space,
+  and change data layout from separate component planes to pixel-interleaved.
+  Works on one pixel row at a time.
+
+* Color quantization: reduce the data to colormapped form, using either an
+  externally specified colormap or an internally generated one.  This module
+  is not used for full-color output.  Works on one pixel row at a time; may
+  require two passes to generate a color map.  Note that the output will
+  always be a single component representing colormap indexes.  In the current
+  design, the output values are JSAMPLEs, so an 8-bit compilation cannot
+  quantize to more than 256 colors.  This is unlikely to be a problem in
+  practice.
+
+* Color reduction: this module handles color precision reduction, e.g.,
+  generating 15-bit color (5 bits/primary) from JPEG's 24-bit output.
+  Not quite clear yet how this should be handled... should we merge it with
+  colorspace conversion???
+
+Note that some high-speed operating modes might condense the entire
+postprocessing sequence to a single module (upsample, color convert, and
+quantize in one step).
+
+In addition to the above objects, the decompression library includes these
+objects:
+
+* Master control: determines the number of passes required, controls overall
+  and per-pass initialization of the other modules.  This is subdivided into
+  input and output control: jdinput.c controls only input-side processing,
+  while jdmaster.c handles overall initialization and output-side control.
+
+* Marker reading: decodes JPEG markers (except for RSTn).
+
+* Data source manager: supplies the input JPEG datastream.  The source
+  manager supplied with the library knows how to read from a stdio stream;
+  for other behaviors, the surrounding application may provide its own source
+  manager.
+
+* Memory manager: same as for compression library.
+
+* Error handler: same as for compression library.
+
+* Progress monitor: same as for compression library.
+
+As with compression, the data source manager, error handler, and progress
+monitor are candidates for replacement by a surrounding application.
+
+
+*** Decompression input and output separation ***
+
+To support efficient incremental display of progressive JPEG files, the
+decompressor is divided into two sections that can run independently:
+
+1. Data input includes marker parsing, entropy decoding, and input into the
+   coefficient controller's DCT coefficient buffer.  Note that this
+   processing is relatively cheap and fast.
+
+2. Data output reads from the DCT coefficient buffer and performs the IDCT
+   and all postprocessing steps.
+
+For a progressive JPEG file, the data input processing is allowed to get
+arbitrarily far ahead of the data output processing.  (This occurs only
+if the application calls jpeg_consume_input(); otherwise input and output
+run in lockstep, since the input section is called only when the output
+section needs more data.)  In this way the application can avoid making
+extra display passes when data is arriving faster than the display pass
+can run.  Furthermore, it is possible to abort an output pass without
+losing anything, since the coefficient buffer is read-only as far as the
+output section is concerned.  See libjpeg.doc for more detail.
+
+A full-image coefficient array is only created if the JPEG file has multiple
+scans (or if the application specifies buffered-image mode anyway).  When
+reading a single-scan file, the coefficient controller normally creates only
+a one-MCU buffer, so input and output processing must run in lockstep in this
+case.  jpeg_consume_input() is effectively a no-op in this situation.
+
+The main impact of dividing the decompressor in this fashion is that we must
+be very careful with shared variables in the cinfo data structure.  Each
+variable that can change during the course of decompression must be
+classified as belonging to data input or data output, and each section must
+look only at its own variables.  For example, the data output section may not
+depend on any of the variables that describe the current scan in the JPEG
+file, because these may change as the data input section advances into a new
+scan.
+
+The progress monitor is (somewhat arbitrarily) defined to treat input of the
+file as one pass when buffered-image mode is not used, and to ignore data
+input work completely when buffered-image mode is used.  Note that the
+library has no reliable way to predict the number of passes when dealing
+with a progressive JPEG file, nor can it predict the number of output passes
+in buffered-image mode.  So the work estimate is inherently bogus anyway.
+
+No comparable division is currently made in the compression library, because
+there isn't any real need for it.
+
+
+*** Data formats ***
+
+Arrays of pixel sample values use the following data structure:
+
+    typedef something JSAMPLE;		a pixel component value, 0..MAXJSAMPLE
+    typedef JSAMPLE *JSAMPROW;		ptr to a row of samples
+    typedef JSAMPROW *JSAMPARRAY;	ptr to a list of rows
+    typedef JSAMPARRAY *JSAMPIMAGE;	ptr to a list of color-component arrays
+
+The basic element type JSAMPLE will typically be one of unsigned char,
+(signed) char, or short.  Short will be used if samples wider than 8 bits are
+to be supported (this is a compile-time option).  Otherwise, unsigned char is
+used if possible.  If the compiler only supports signed chars, then it is
+necessary to mask off the value when reading.  Thus, all reads of JSAMPLE
+values must be coded as "GETJSAMPLE(value)", where the macro will be defined
+as "((value) & 0xFF)" on signed-char machines and "((int) (value))" elsewhere.
+
+With these conventions, JSAMPLE values can be assumed to be >= 0.  This helps
+simplify correct rounding during downsampling, etc.  The JPEG standard's
+specification that sample values run from -128..127 is accommodated by
+subtracting 128 just as the sample value is copied into the source array for
+the DCT step (this will be an array of signed ints).  Similarly, during
+decompression the output of the IDCT step will be immediately shifted back to
+0..255.  (NB: different values are required when 12-bit samples are in use.
+The code is written in terms of MAXJSAMPLE and CENTERJSAMPLE, which will be
+defined as 255 and 128 respectively in an 8-bit implementation, and as 4095
+and 2048 in a 12-bit implementation.)
+
+We use a pointer per row, rather than a two-dimensional JSAMPLE array.  This
+choice costs only a small amount of memory and has several benefits:
+* Code using the data structure doesn't need to know the allocated width of
+  the rows.  This simplifies edge expansion/compression, since we can work
+  in an array that's wider than the logical picture width.
+* Indexing doesn't require multiplication; this is a performance win on many
+  machines.
+* Arrays with more than 64K total elements can be supported even on machines
+  where malloc() cannot allocate chunks larger than 64K.
+* The rows forming a component array may be allocated at different times
+  without extra copying.  This trick allows some speedups in smoothing steps
+  that need access to the previous and next rows.
+
+Note that each color component is stored in a separate array; we don't use the
+traditional layout in which the components of a pixel are stored together.
+This simplifies coding of modules that work on each component independently,
+because they don't need to know how many components there are.  Furthermore,
+we can read or write each component to a temporary file independently, which
+is helpful when dealing with noninterleaved JPEG files.
+
+In general, a specific sample value is accessed by code such as
+	GETJSAMPLE(image[colorcomponent][row][col])
+where col is measured from the image left edge, but row is measured from the
+first sample row currently in memory.  Either of the first two indexings can
+be precomputed by copying the relevant pointer.
+
+
+Since most image-processing applications prefer to work on images in which
+the components of a pixel are stored together, the data passed to or from the
+surrounding application uses the traditional convention: a single pixel is
+represented by N consecutive JSAMPLE values, and an image row is an array of
+(# of color components)*(image width) JSAMPLEs.  One or more rows of data can
+be represented by a pointer of type JSAMPARRAY in this scheme.  This scheme is
+converted to component-wise storage inside the JPEG library.  (Applications
+that want to skip JPEG preprocessing or postprocessing will have to contend
+with component-wise storage.)
+
+
+Arrays of DCT-coefficient values use the following data structure:
+
+    typedef short JCOEF;		a 16-bit signed integer
+    typedef JCOEF JBLOCK[DCTSIZE2];	an 8x8 block of coefficients
+    typedef JBLOCK *JBLOCKROW;		ptr to one horizontal row of 8x8 blocks
+    typedef JBLOCKROW *JBLOCKARRAY;	ptr to a list of such rows
+    typedef JBLOCKARRAY *JBLOCKIMAGE;	ptr to a list of color component arrays
+
+The underlying type is at least a 16-bit signed integer; while "short" is big
+enough on all machines of interest, on some machines it is preferable to use
+"int" for speed reasons, despite the storage cost.  Coefficients are grouped
+into 8x8 blocks (but we always use #defines DCTSIZE and DCTSIZE2 rather than
+"8" and "64").
+
+The contents of a coefficient block may be in either "natural" or zigzagged
+order, and may be true values or divided by the quantization coefficients,
+depending on where the block is in the processing pipeline.  In the current
+library, coefficient blocks are kept in natural order everywhere; the entropy
+codecs zigzag or dezigzag the data as it is written or read.  The blocks
+contain quantized coefficients everywhere outside the DCT/IDCT subsystems.
+(This latter decision may need to be revisited to support variable
+quantization a la JPEG Part 3.)
+
+Notice that the allocation unit is now a row of 8x8 blocks, corresponding to
+eight rows of samples.  Otherwise the structure is much the same as for
+samples, and for the same reasons.
+
+On machines where malloc() can't handle a request bigger than 64Kb, this data
+structure limits us to rows of less than 512 JBLOCKs, or a picture width of
+4000+ pixels.  This seems an acceptable restriction.
+
+
+On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW)
+must be declared as "far" pointers, but the upper levels can be "near"
+(implying that the pointer lists are allocated in the DS segment).
+We use a #define symbol FAR, which expands to the "far" keyword when
+compiling on 80x86 machines and to nothing elsewhere.
+
+
+*** Suspendable processing ***
+
+In some applications it is desirable to use the JPEG library as an
+incremental, memory-to-memory filter.  In this situation the data source or
+destination may be a limited-size buffer, and we can't rely on being able to
+empty or refill the buffer at arbitrary times.  Instead the application would
+like to have control return from the library at buffer overflow/underrun, and
+then resume compression or decompression at a later time.
+
+This scenario is supported for simple cases.  (For anything more complex, we
+recommend that the application "bite the bullet" and develop real multitasking
+capability.)  The libjpeg.doc file goes into more detail about the usage and
+limitations of this capability; here we address the implications for library
+structure.
+
+The essence of the problem is that the entropy codec (coder or decoder) must
+be prepared to stop at arbitrary times.  In turn, the controllers that call
+the entropy codec must be able to stop before having produced or consumed all
+the data that they normally would handle in one call.  That part is reasonably
+straightforward: we make the controller call interfaces include "progress
+counters" which indicate the number of data chunks successfully processed, and
+we require callers to test the counter rather than just assume all of the data
+was processed.
+
+Rather than trying to restart at an arbitrary point, the current Huffman
+codecs are designed to restart at the beginning of the current MCU after a
+suspension due to buffer overflow/underrun.  At the start of each call, the
+codec's internal state is loaded from permanent storage (in the JPEG object
+structures) into local variables.  On successful completion of the MCU, the
+permanent state is updated.  (This copying is not very expensive, and may even
+lead to *improved* performance if the local variables can be registerized.)
+If a suspension occurs, the codec simply returns without updating the state,
+thus effectively reverting to the start of the MCU.  Note that this implies
+leaving some data unprocessed in the source/destination buffer (ie, the
+compressed partial MCU).  The data source/destination module interfaces are
+specified so as to make this possible.  This also implies that the data buffer
+must be large enough to hold a worst-case compressed MCU; a couple thousand
+bytes should be enough.
+
+In a successive-approximation AC refinement scan, the progressive Huffman
+decoder has to be able to undo assignments of newly nonzero coefficients if it
+suspends before the MCU is complete, since decoding requires distinguishing
+previously-zero and previously-nonzero coefficients.  This is a bit tedious
+but probably won't have much effect on performance.  Other variants of Huffman
+decoding need not worry about this, since they will just store the same values
+again if forced to repeat the MCU.
+
+This approach would probably not work for an arithmetic codec, since its
+modifiable state is quite large and couldn't be copied cheaply.  Instead it
+would have to suspend and resume exactly at the point of the buffer end.
+
+The JPEG marker reader is designed to cope with suspension at an arbitrary
+point.  It does so by backing up to the start of the marker parameter segment,
+so the data buffer must be big enough to hold the largest marker of interest.
+Again, a couple KB should be adequate.  (A special "skip" convention is used
+to bypass COM and APPn markers, so these can be larger than the buffer size
+without causing problems; otherwise a 64K buffer would be needed in the worst
+case.)
+
+The JPEG marker writer currently does *not* cope with suspension.  I feel that
+this is not necessary; it is much easier simply to require the application to
+ensure there is enough buffer space before starting.  (An empty 2K buffer is
+more than sufficient for the header markers; and ensuring there are a dozen or
+two bytes available before calling jpeg_finish_compress() will suffice for the
+trailer.)  This would not work for writing multi-scan JPEG files, but
+we simply do not intend to support that capability with suspension.
+
+
+*** Memory manager services ***
+
+The JPEG library's memory manager controls allocation and deallocation of
+memory, and it manages large "virtual" data arrays on machines where the
+operating system does not provide virtual memory.  Note that the same
+memory manager serves both compression and decompression operations.
+
+In all cases, allocated objects are tied to a particular compression or
+decompression master record, and they will be released when that master
+record is destroyed.
+
+The memory manager does not provide explicit deallocation of objects.
+Instead, objects are created in "pools" of free storage, and a whole pool
+can be freed at once.  This approach helps prevent storage-leak bugs, and
+it speeds up operations whenever malloc/free are slow (as they often are).
+The pools can be regarded as lifetime identifiers for objects.  Two
+pools/lifetimes are defined:
+  * JPOOL_PERMANENT	lasts until master record is destroyed
+  * JPOOL_IMAGE		lasts until done with image (JPEG datastream)
+Permanent lifetime is used for parameters and tables that should be carried
+across from one datastream to another; this includes all application-visible
+parameters.  Image lifetime is used for everything else.  (A third lifetime,
+JPOOL_PASS = one processing pass, was originally planned.  However it was
+dropped as not being worthwhile.  The actual usage patterns are such that the
+peak memory usage would be about the same anyway; and having per-pass storage
+substantially complicates the virtual memory allocation rules --- see below.)
+
+The memory manager deals with three kinds of object:
+1. "Small" objects.  Typically these require no more than 10K-20K total.
+2. "Large" objects.  These may require tens to hundreds of K depending on
+   image size.  Semantically they behave the same as small objects, but we
+   distinguish them for two reasons:
+     * On MS-DOS machines, large objects are referenced by FAR pointers,
+       small objects by NEAR pointers.
+     * Pool allocation heuristics may differ for large and small objects.
+   Note that individual "large" objects cannot exceed the size allowed by
+   type size_t, which may be 64K or less on some machines.
+3. "Virtual" objects.  These are large 2-D arrays of JSAMPLEs or JBLOCKs
+   (typically large enough for the entire image being processed).  The
+   memory manager provides stripwise access to these arrays.  On machines
+   without virtual memory, the rest of the array may be swapped out to a
+   temporary file.
+
+(Note: JSAMPARRAY and JBLOCKARRAY data structures are a combination of large
+objects for the data proper and small objects for the row pointers.  For
+convenience and speed, the memory manager provides single routines to create
+these structures.  Similarly, virtual arrays include a small control block
+and a JSAMPARRAY or JBLOCKARRAY working buffer, all created with one call.)
+
+In the present implementation, virtual arrays are only permitted to have image
+lifespan.  (Permanent lifespan would not be reasonable, and pass lifespan is
+not very useful since a virtual array's raison d'etre is to store data for
+multiple passes through the image.)  We also expect that only "small" objects
+will be given permanent lifespan, though this restriction is not required by
+the memory manager.
+
+In a non-virtual-memory machine, some performance benefit can be gained by
+making the in-memory buffers for virtual arrays be as large as possible.
+(For small images, the buffers might fit entirely in memory, so blind
+swapping would be very wasteful.)  The memory manager will adjust the height
+of the buffers to fit within a prespecified maximum memory usage.  In order
+to do this in a reasonably optimal fashion, the manager needs to allocate all
+of the virtual arrays at once.  Therefore, there isn't a one-step allocation
+routine for virtual arrays; instead, there is a "request" routine that simply
+allocates the control block, and a "realize" routine (called just once) that
+determines space allocation and creates all of the actual buffers.  The
+realize routine must allow for space occupied by non-virtual large objects.
+(We don't bother to factor in the space needed for small objects, on the
+grounds that it isn't worth the trouble.)
+
+To support all this, we establish the following protocol for doing business
+with the memory manager:
+  1. Modules must request virtual arrays (which may have only image lifespan)
+     during the initial setup phase, i.e., in their jinit_xxx routines.
+  2. All "large" objects (including JSAMPARRAYs and JBLOCKARRAYs) must also be
+     allocated during initial setup.
+  3. realize_virt_arrays will be called at the completion of initial setup.
+     The above conventions ensure that sufficient information is available
+     for it to choose a good size for virtual array buffers.
+Small objects of any lifespan may be allocated at any time.  We expect that
+the total space used for small objects will be small enough to be negligible
+in the realize_virt_arrays computation.
+
+In a virtual-memory machine, we simply pretend that the available space is
+infinite, thus causing realize_virt_arrays to decide that it can allocate all
+the virtual arrays as full-size in-memory buffers.  The overhead of the
+virtual-array access protocol is very small when no swapping occurs.
+
+A virtual array can be specified to be "pre-zeroed"; when this flag is set,
+never-yet-written sections of the array are set to zero before being made
+available to the caller.  If this flag is not set, never-written sections
+of the array contain garbage.  (This feature exists primarily because the
+equivalent logic would otherwise be needed in jdcoefct.c for progressive
+JPEG mode; we may as well make it available for possible other uses.)
+
+The first write pass on a virtual array is required to occur in top-to-bottom
+order; read passes, as well as any write passes after the first one, may
+access the array in any order.  This restriction exists partly to simplify
+the virtual array control logic, and partly because some file systems may not
+support seeking beyond the current end-of-file in a temporary file.  The main
+implication of this restriction is that rearrangement of rows (such as
+converting top-to-bottom data order to bottom-to-top) must be handled while
+reading data out of the virtual array, not while putting it in.
+
+
+*** Memory manager internal structure ***
+
+To isolate system dependencies as much as possible, we have broken the
+memory manager into two parts.  There is a reasonably system-independent
+"front end" (jmemmgr.c) and a "back end" that contains only the code
+likely to change across systems.  All of the memory management methods
+outlined above are implemented by the front end.  The back end provides
+the following routines for use by the front end (none of these routines
+are known to the rest of the JPEG code):
+
+jpeg_mem_init, jpeg_mem_term	system-dependent initialization/shutdown
+
+jpeg_get_small, jpeg_free_small	interface to malloc and free library routines
+				(or their equivalents)
+
+jpeg_get_large, jpeg_free_large	interface to FAR malloc/free in MSDOS machines;
+				else usually the same as
+				jpeg_get_small/jpeg_free_small
+
+jpeg_mem_available		estimate available memory
+
+jpeg_open_backing_store		create a backing-store object
+
+read_backing_store,		manipulate a backing-store object
+write_backing_store,
+close_backing_store
+
+On some systems there will be more than one type of backing-store object
+(specifically, in MS-DOS a backing store file might be an area of extended
+memory as well as a disk file).  jpeg_open_backing_store is responsible for
+choosing how to implement a given object.  The read/write/close routines
+are method pointers in the structure that describes a given object; this
+lets them be different for different object types.
+
+It may be necessary to ensure that backing store objects are explicitly
+released upon abnormal program termination.  For example, MS-DOS won't free
+extended memory by itself.  To support this, we will expect the main program
+or surrounding application to arrange to call self_destruct (typically via
+jpeg_destroy) upon abnormal termination.  This may require a SIGINT signal
+handler or equivalent.  We don't want to have the back end module install its
+own signal handler, because that would pre-empt the surrounding application's
+ability to control signal handling.
+
+The IJG distribution includes several memory manager back end implementations.
+Usually the same back end should be suitable for all applications on a given
+system, but it is possible for an application to supply its own back end at
+need.
+
+
+*** Implications of DNL marker ***
+
+Some JPEG files may use a DNL marker to postpone definition of the image
+height (this would be useful for a fax-like scanner's output, for instance).
+In these files the SOF marker claims the image height is 0, and you only
+find out the true image height at the end of the first scan.
+
+We could read these files as follows:
+1. Upon seeing zero image height, replace it by 65535 (the maximum allowed).
+2. When the DNL is found, update the image height in the global image
+   descriptor.
+This implies that control modules must avoid making copies of the image
+height, and must re-test for termination after each MCU row.  This would
+be easy enough to do.
+
+In cases where image-size data structures are allocated, this approach will
+result in very inefficient use of virtual memory or much-larger-than-necessary
+temporary files.  This seems acceptable for something that probably won't be a
+mainstream usage.  People might have to forgo use of memory-hogging options
+(such as two-pass color quantization or noninterleaved JPEG files) if they
+want efficient conversion of such files.  (One could improve efficiency by
+demanding a user-supplied upper bound for the height, less than 65536; in most
+cases it could be much less.)
+
+The standard also permits the SOF marker to overestimate the image height,
+with a DNL to give the true, smaller height at the end of the first scan.
+This would solve the space problems if the overestimate wasn't too great.
+However, it implies that you don't even know whether DNL will be used.
+
+This leads to a couple of very serious objections:
+1. Testing for a DNL marker must occur in the inner loop of the decompressor's
+   Huffman decoder; this implies a speed penalty whether the feature is used
+   or not.
+2. There is no way to hide the last-minute change in image height from an
+   application using the decoder.  Thus *every* application using the IJG
+   library would suffer a complexity penalty whether it cared about DNL or
+   not.
+We currently do not support DNL because of these problems.
+
+A different approach is to insist that DNL-using files be preprocessed by a
+separate program that reads ahead to the DNL, then goes back and fixes the SOF
+marker.  This is a much simpler solution and is probably far more efficient.
+Even if one wants piped input, buffering the first scan of the JPEG file needs
+a lot smaller temp file than is implied by the maximum-height method.  For
+this approach we'd simply treat DNL as a no-op in the decompressor (at most,
+check that it matches the SOF image height).
+
+We will not worry about making the compressor capable of outputting DNL.
+Something similar to the first scheme above could be applied if anyone ever
+wants to make that work.