1 //============================================================================
2 //  Copyright (c) Kitware, Inc.
3 //  All rights reserved.
4 //  See LICENSE.txt for details.
5 //
6 //  This software is distributed WITHOUT ANY WARRANTY; without even
7 //  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 //  PURPOSE.  See the above copyright notice for more information.
9 //============================================================================
10 
11 #include <vtkm/cont/testing/Testing.h>
12 #include <vtkm/io/PixelTypes.h>
13 
14 #include <string>
15 
16 using namespace vtkm::io;
17 
18 template <typename PixelType>
TestPixelTypeOperations(const vtkm::UInt16 & numPixels=10)19 void TestPixelTypeOperations(const vtkm::UInt16& numPixels = 10)
20 {
21   using ValType = typename PixelType::ComponentType;
22   const ValType numBytes = static_cast<ValType>(PixelType::NUM_BYTES);
23   const ValType numChannels = static_cast<ValType>(PixelType::NUM_CHANNELS);
24 
25   // Fill in the imageData through FillPixelData
26   std::vector<unsigned char> imageData(numPixels * numBytes * numChannels);
27   std::vector<PixelType> pixelVector(numPixels);
28   for (ValType i = 0; i < numPixels; i++)
29   {
30     ValType pixelVal = 0;
31     for (ValType j = 0, shift = numBytes - 1; j < numBytes; shift--, j++)
32     {
33       pixelVal += (i + j) << (shift * 8);
34     }
35 
36     PixelType pixel(pixelVal);
37     pixelVector[i] = pixel;
38     pixel.FillImageAtIndexWithPixel(imageData.data(), i);
39   }
40 
41   // Test that the imageData values were set correctly
42   VTKM_TEST_ASSERT(static_cast<vtkm::Id>(imageData.size()) == numPixels * numChannels * numBytes,
43                    "Wrong number of elements");
44   for (ValType j = 0; j < numBytes; j++)
45   {
46     for (ValType i = 0; i < numPixels; i++)
47     {
48       for (ValType k = numChannels * i; k < numChannels * i + numChannels; k++)
49       {
50         VTKM_TEST_ASSERT(imageData[k * numBytes + j] == i + j,
51                          "Wrong value at index[" + std::to_string(k * numBytes + j) +
52                            "]: " + std::to_string(imageData[k * numBytes + j]) +
53                            " != " + std::to_string(i + j));
54       }
55     }
56   }
57 
58   // Test that a pixel can be retreived from the filled out data vector
59   for (vtkm::Id i = 0; i < numPixels; i++)
60   {
61     VTKM_TEST_ASSERT(pixelVector[static_cast<typename std::vector<PixelType>::size_type>(i)] ==
62                        PixelType(imageData.data(), i),
63                      "Incorrect pixel value");
64   }
65 }
66 
TestDifferentPixelTypes()67 void TestDifferentPixelTypes()
68 {
69   VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Testing 8 bit RGB");
70   TestPixelTypeOperations<RGBPixel_8>();
71 
72   VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Testing 8 bit Grey");
73   TestPixelTypeOperations<GreyPixel_8>();
74 
75   VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Testing 16 bit RGB");
76   TestPixelTypeOperations<RGBPixel_16>();
77 
78   VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Testing 16 bit Grey");
79   TestPixelTypeOperations<GreyPixel_16>();
80 }
81 
TestGreyPixelConstructors()82 void TestGreyPixelConstructors()
83 {
84   std::vector<unsigned char> initData{ 1, 2 };
85 
86   auto pixel_1 = GreyPixel_8(1);
87   auto pixel_2 = GreyPixel_8(1);
88   auto pixel_3 = GreyPixel_8(2);
89   auto pixel_4 = GreyPixel_8(initData.data(), 0);
90   auto pixel_5 = GreyPixel_8(initData.data(), 1);
91   auto pixel_6 = GreyPixel_16(initData.data(), 0);
92 
93   float color = 10.0f / GreyPixel_16::MAX_COLOR_VALUE;
94   auto pixel_7 = GreyPixel_16({ color, color, color, 5 });
95 
96   VTKM_TEST_ASSERT(vtkm::UInt16(1) == pixel_1[0], "Type mis-match");
97   VTKM_TEST_ASSERT(vtkm::FloatDefault(0) == pixel_1.Diff(pixel_2), "Incorrect Diff");
98   VTKM_TEST_ASSERT(vtkm::FloatDefault(1) == pixel_1.Diff(pixel_3), "Incorrect Diff");
99   VTKM_TEST_ASSERT(vtkm::Vec4f_32(1.0f / 255, 1.0f / 255, 1.0f / 255, 1) == pixel_1.ToVec4f(),
100                    "Incorrect Conversion");
101   VTKM_TEST_ASSERT(vtkm::Vec<vtkm::UInt8, 1>(1) == pixel_4, "Bad 1st value 8 bit construct");
102   VTKM_TEST_ASSERT(vtkm::Vec<vtkm::UInt8, 1>(2) == pixel_5, "Bad 2nd value 8 bit construct");
103   VTKM_TEST_ASSERT(vtkm::Vec<vtkm::UInt16, 1>(258) == pixel_6, "Bad 16 bit construct");
104   VTKM_TEST_ASSERT(vtkm::Vec4f_32(258.0f / 65535, 258.0f / 65535, 258.0f / 65535, 1) ==
105                      pixel_6.ToVec4f(),
106                    "Incorrect Conversion");
107   VTKM_TEST_ASSERT(vtkm::Vec<vtkm::UInt16, 1>(10) == pixel_7, "Bad Vec4f_32 construction");
108 
109   VTKM_TEST_ASSERT(GreyPixel<16>::BIT_DEPTH == 16, "Bad BitDepth");
110   VTKM_TEST_ASSERT(GreyPixel<16>::NUM_BYTES == 2, "Bad NumBytes");
111   VTKM_TEST_ASSERT(GreyPixel<16>::MAX_COLOR_VALUE == 65535, "Bad NumBytes");
112   VTKM_TEST_ASSERT(GreyPixel<16>::NUM_CHANNELS == 1, "Bad NumChannels");
113   VTKM_TEST_ASSERT(GreyPixel<16>::BYTES_PER_PIXEL == 2, "Wrong Pixel Byte distance");
114 
115   // Shouldn't compile
116   // auto pixel_4 = RGBPixel_8(1, 1, 1);
117   // pixel_1.Diff(pixel_4);
118 }
119 
TestRGBPixelConstructors()120 void TestRGBPixelConstructors()
121 {
122   std::vector<unsigned char> initData{ 1, 2, 3, 4, 5, 6 };
123 
124   auto pixel_1 = RGBPixel_8(1, 1, 1);
125   auto pixel_2 = RGBPixel_8(1, 1, 1);
126   auto pixel_3 = RGBPixel_8(1);
127   auto pixel_4 = RGBPixel_8(2, 2, 2);
128   auto pixel_5 = RGBPixel_8(initData.data(), 0);
129   auto pixel_6 = RGBPixel_8(initData.data(), 1);
130   auto pixel_7 = RGBPixel_16(initData.data(), 0);
131 
132   float color = 10.0f / RGBPixel_16::MAX_COLOR_VALUE;
133   auto pixel_8 = RGBPixel_16({ color, color, color, 5 });
134 
135   VTKM_TEST_ASSERT(vtkm::Vec3ui_8(1, 1, 1) == pixel_1, "Type mis-match");
136   VTKM_TEST_ASSERT(vtkm::FloatDefault(0) == pixel_1.Diff(pixel_2), "Incorrect Diff");
137   VTKM_TEST_ASSERT(vtkm::FloatDefault(0) == pixel_1.Diff(pixel_3), "Incorrect Diff");
138   VTKM_TEST_ASSERT(vtkm::FloatDefault(3) == pixel_1.Diff(pixel_4), "Incorrect Diff");
139   VTKM_TEST_ASSERT(vtkm::Vec4f_32(1.0f / 255, 1.0f / 255, 1.0f / 255, 1) == pixel_1.ToVec4f(),
140                    "Incorrect Conversion");
141   VTKM_TEST_ASSERT(vtkm::Vec3ui_8(1, 2, 3) == pixel_5, "Bad 1st value 8 bit construct");
142   VTKM_TEST_ASSERT(vtkm::Vec3ui_8(4, 5, 6) == pixel_6, "Bad 2nd value 8 bit construct");
143   VTKM_TEST_ASSERT(vtkm::Vec3ui_16(258, 772, 1286) == pixel_7, "Bad 16 bit construct");
144   VTKM_TEST_ASSERT(vtkm::Vec4f_32(258.0f / 65535, 772.0f / 65535, 1286.0f / 65535, 1) ==
145                      pixel_7.ToVec4f(),
146                    "Incorrect Conversion");
147   VTKM_TEST_ASSERT(vtkm::Vec<vtkm::UInt16, 3>(10, 10, 10) == pixel_8, "Bad Vec4f_32 construction");
148 
149   VTKM_TEST_ASSERT(RGBPixel<16>::BIT_DEPTH == 16, "Bad BitDepth");
150   VTKM_TEST_ASSERT(RGBPixel<16>::NUM_BYTES == 2, "Bad NumBytes");
151   VTKM_TEST_ASSERT(RGBPixel<16>::MAX_COLOR_VALUE == 65535, "Bad NumBytes");
152   VTKM_TEST_ASSERT(RGBPixel<16>::NUM_CHANNELS == 3, "Bad NumChannels");
153   VTKM_TEST_ASSERT(RGBPixel<16>::BYTES_PER_PIXEL == 6, "Wrong Pixel Byte distance");
154 
155   // Shouldn't compile
156   // auto pixel_8 = GreyPixel_8(1);
157   // pixel_1.Diff(pixel_8);
158 }
159 
TestPixelTypes()160 void TestPixelTypes()
161 {
162   VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Testing RGBPixel");
163   TestRGBPixelConstructors();
164 
165   VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Testing GreyPixel");
166   TestGreyPixelConstructors();
167 
168   VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Testing Pixel Types");
169   TestDifferentPixelTypes();
170 }
171 
UnitTestPixelTypes(int argc,char * argv[])172 int UnitTestPixelTypes(int argc, char* argv[])
173 {
174   return vtkm::cont::testing::Testing::Run(TestPixelTypes, argc, argv);
175 }
176