Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
Core/test/mitkDICOMLocaleTest.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 /*
18  This test is meant to reproduce the following error:
19 
20  - The machine or current user has a German locale.
21  - This esp. means that stream IO expects the decimal separator as a comma: ","
22  - DICOM files use a point "." as the decimal separator to be locale independent
23  - The parser used by MITK (ITK's GDCM) seems to use the current locale instead of the "C" or "POSIX" locale
24  - This leads to spacings (and probably other numbers) being trimmed/rounded,
25  e.g. the correct spacing of 0.314 is read as 1.0 etc.
26 
27 */
28 
29 #include "mitkDicomSeriesReader.h"
30 #include "mitkIOUtil.h"
31 #include "mitkImage.h"
33 
34 #include "mitkTestFixture.h"
35 #include "mitkTestingMacros.h"
36 
37 #include <list>
38 #include <locale.h>
39 #include <locale>
40 
41 class mitkDICOMLocaleTestSuite : public mitk::TestFixture
42 {
43  CPPUNIT_TEST_SUITE(mitkDICOMLocaleTestSuite);
44  CPPUNIT_TEST_SUITE_ADD_CUSTOM_TESTS(addDICOMLocaleWithReferenceImageTests);
45  CPPUNIT_TEST_SUITE_END();
46 
47 private:
48  // A custom method for adding a combination of filename and locale tests
49  static void addDICOMLocaleWithReferenceImageTests(TestSuiteBuilderContextType &context)
50  {
51  std::vector<std::string> fileArgs;
52  fileArgs.push_back("spacing-ok-ct.dcm");
53  fileArgs.push_back("spacing-ok-mr.dcm");
54  fileArgs.push_back("spacing-ok-sc.dcm");
55 
56  // load a reference DICOM file with German locales being set
57  std::vector<std::string> localeArgs;
58  localeArgs.push_back("C");
59  localeArgs.push_back("de_DE");
60  localeArgs.push_back("de_DE.utf8");
61  localeArgs.push_back("de_DE.UTF8");
62  localeArgs.push_back("de_DE@euro");
63  localeArgs.push_back("German_Germany");
64 
65  for (std::size_t fileIndex = 0; fileIndex < fileArgs.size(); ++fileIndex)
66  {
67  for (std::size_t localeIndex = 0; localeIndex < localeArgs.size(); ++localeIndex)
68  {
69  MITK_PARAMETERIZED_TEST_2(testLocaleWithReferenceImage, fileArgs[fileIndex], localeArgs[localeIndex]);
70  }
71  }
72  }
73 
74 private:
75  std::string m_FileName;
76  std::string m_Locale;
77  bool m_SkipImageTest;
78 
79  char *m_OldLocale;
80 
81  void SetTestParameter()
82  {
83  std::vector<std::string> parameter = GetTestParameter();
84  CPPUNIT_ASSERT(parameter.size() == 2);
85  m_FileName = GetTestDataFilePath(parameter[0]);
86  m_Locale = parameter[1];
87  }
88 
89 public:
90  mitkDICOMLocaleTestSuite() : m_OldLocale(NULL), m_SkipImageTest(false) {}
91  // Change the current locale to m_Locale
92  void setUp() override
93  {
94  m_SkipImageTest = false;
95  m_OldLocale = NULL;
96  SetTestParameter();
97 
98  try
99  {
100  m_OldLocale = setlocale(LC_ALL, NULL);
101  MITK_TEST_OUTPUT(<< " ** Changing locale from " << m_OldLocale << " to '" << m_Locale << "'")
102  setlocale(LC_ALL, m_Locale.c_str());
103  std::cin.imbue(std::locale(m_Locale.c_str()));
104  }
105  catch (...)
106  {
107  MITK_TEST_OUTPUT(<< "Could not activate locale " << m_Locale)
108  m_SkipImageTest = true;
109  }
110  }
111 
112  void tearDown() override
113  {
114  if (m_OldLocale)
115  {
116  setlocale(LC_ALL, m_OldLocale);
117  std::cin.imbue(std::locale(m_OldLocale));
118  }
119  }
120 
121  void testLocaleWithReferenceImage()
122  {
123  if (m_SkipImageTest)
124  return;
125 
126  mitk::Image::Pointer image = mitk::IOUtil::LoadImage(m_FileName);
127  CPPUNIT_ASSERT(image.IsNotNull());
128 
129  // note importance of minor differences in spacings:
130  // DICOM has order y-spacing, x-spacing, while in MITK we assume x-spacing, y-spacing (both meant for 0 and 1 index
131  // in array)
132  CPPUNIT_ASSERT_MESSAGE("incorrect x spacing", mitk::Equal(image->GetGeometry()->GetSpacing()[0], 0.3141592));
133  CPPUNIT_ASSERT_MESSAGE("incorrect y spacing ", mitk::Equal(image->GetGeometry()->GetSpacing()[1], 0.3411592));
134  }
135 };
136 
137 MITK_TEST_SUITE_REGISTRATION(mitkDICOMLocale)
MITK_TEST_SUITE_REGISTRATION(mitkImageToItk)
STL namespace.
static std::string GetTestDataFilePath(const std::string &testData)
Get the absolute path for test data.
#define MITK_PARAMETERIZED_TEST_2(TESTMETHOD, arg1, arg2)
Adds a parameterized test to the current test suite.
#define MITK_TEST_OUTPUT(x)
Output some text.
std::vector< std::string > GetTestParameter() const
Get parameters for this test fixture.
Test fixture for parameterized tests.
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.
static mitk::Image::Pointer LoadImage(const std::string &path)
LoadImage Convenience method to load an arbitrary mitkImage.
Definition: mitkIOUtil.cpp:597