comparison OrthancFramework/UnitTestsSources/ImageProcessingTests.cpp @ 4044:d25f4c0fa160 framework

splitting code into OrthancFramework and OrthancServer
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 10 Jun 2020 20:30:34 +0200
parents UnitTestsSources/ImageProcessingTests.cpp@27628b0f6ada
children 05b8fd21089c
comparison
equal deleted inserted replaced
4043:6c6239aec462 4044:d25f4c0fa160
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * In addition, as a special exception, the copyright holders of this
13 * program give permission to link the code of its release with the
14 * OpenSSL project's "OpenSSL" library (or with modified versions of it
15 * that use the same license as the "OpenSSL" library), and distribute
16 * the linked executables. You must obey the GNU General Public License
17 * in all respects for all of the code used other than "OpenSSL". If you
18 * modify file(s) with this exception, you may extend this exception to
19 * your version of the file(s), but you are not obligated to do so. If
20 * you do not wish to do so, delete this exception statement from your
21 * version. If you delete this exception statement from all source files
22 * in the program, then also delete it here.
23 *
24 * This program is distributed in the hope that it will be useful, but
25 * WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 **/
32
33
34 #if ORTHANC_UNIT_TESTS_LINK_FRAMEWORK == 1
35 # include <OrthancFramework.h>
36 #endif
37
38 #include "PrecompiledHeadersUnitTests.h"
39 #include "gtest/gtest.h"
40
41 #include "../Core/Compatibility.h"
42 #include "../Core/DicomFormat/DicomImageInformation.h"
43 #include "../Core/Images/Image.h"
44 #include "../Core/Images/ImageProcessing.h"
45 #include "../Core/Images/ImageTraits.h"
46 #include "../Core/OrthancException.h"
47
48 #include <memory>
49
50 using namespace Orthanc;
51
52
53 TEST(DicomImageInformation, ExtractPixelFormat1)
54 {
55 // Cardiac/MR*
56 DicomMap m;
57 m.SetValue(DICOM_TAG_ROWS, "24", false);
58 m.SetValue(DICOM_TAG_COLUMNS, "16", false);
59 m.SetValue(DICOM_TAG_BITS_ALLOCATED, "16", false);
60 m.SetValue(DICOM_TAG_SAMPLES_PER_PIXEL, "1", false);
61 m.SetValue(DICOM_TAG_BITS_STORED, "12", false);
62 m.SetValue(DICOM_TAG_HIGH_BIT, "11", false);
63 m.SetValue(DICOM_TAG_PIXEL_REPRESENTATION, "0", false);
64 m.SetValue(DICOM_TAG_PHOTOMETRIC_INTERPRETATION, "MONOCHROME2", false);
65
66 DicomImageInformation info(m);
67 PixelFormat format;
68 ASSERT_TRUE(info.ExtractPixelFormat(format, false));
69 ASSERT_EQ(PixelFormat_Grayscale16, format);
70 }
71
72
73 TEST(DicomImageInformation, ExtractPixelFormat2)
74 {
75 // Delphine CT
76 DicomMap m;
77 m.SetValue(DICOM_TAG_ROWS, "24", false);
78 m.SetValue(DICOM_TAG_COLUMNS, "16", false);
79 m.SetValue(DICOM_TAG_BITS_ALLOCATED, "16", false);
80 m.SetValue(DICOM_TAG_SAMPLES_PER_PIXEL, "1", false);
81 m.SetValue(DICOM_TAG_BITS_STORED, "16", false);
82 m.SetValue(DICOM_TAG_HIGH_BIT, "15", false);
83 m.SetValue(DICOM_TAG_PIXEL_REPRESENTATION, "1", false);
84 m.SetValue(DICOM_TAG_PHOTOMETRIC_INTERPRETATION, "MONOCHROME2", false);
85
86 DicomImageInformation info(m);
87 PixelFormat format;
88 ASSERT_TRUE(info.ExtractPixelFormat(format, false));
89 ASSERT_EQ(PixelFormat_SignedGrayscale16, format);
90 }
91
92
93
94 namespace
95 {
96 template <typename T>
97 class TestImageTraits : public ::testing::Test
98 {
99 private:
100 std::unique_ptr<Image> image_;
101
102 protected:
103 virtual void SetUp() ORTHANC_OVERRIDE
104 {
105 image_.reset(new Image(ImageTraits::PixelTraits::GetPixelFormat(), 7, 9, false));
106 }
107
108 virtual void TearDown() ORTHANC_OVERRIDE
109 {
110 image_.reset(NULL);
111 }
112
113 public:
114 typedef T ImageTraits;
115
116 ImageAccessor& GetImage()
117 {
118 return *image_;
119 }
120 };
121
122 template <typename T>
123 class TestIntegerImageTraits : public TestImageTraits<T>
124 {
125 };
126 }
127
128
129 typedef ::testing::Types<
130 ImageTraits<PixelFormat_Grayscale8>,
131 ImageTraits<PixelFormat_Grayscale16>,
132 ImageTraits<PixelFormat_SignedGrayscale16>
133 > IntegerFormats;
134 TYPED_TEST_CASE(TestIntegerImageTraits, IntegerFormats);
135
136 typedef ::testing::Types<
137 ImageTraits<PixelFormat_Grayscale8>,
138 ImageTraits<PixelFormat_Grayscale16>,
139 ImageTraits<PixelFormat_SignedGrayscale16>,
140 ImageTraits<PixelFormat_RGB24>,
141 ImageTraits<PixelFormat_BGRA32>
142 > AllFormats;
143 TYPED_TEST_CASE(TestImageTraits, AllFormats);
144
145
146 TYPED_TEST(TestImageTraits, SetZero)
147 {
148 ImageAccessor& image = this->GetImage();
149
150 memset(image.GetBuffer(), 128, image.GetHeight() * image.GetWidth());
151
152 switch (image.GetFormat())
153 {
154 case PixelFormat_Grayscale8:
155 case PixelFormat_Grayscale16:
156 case PixelFormat_SignedGrayscale16:
157 ImageProcessing::Set(image, 0);
158 break;
159
160 case PixelFormat_RGB24:
161 case PixelFormat_BGRA32:
162 ImageProcessing::Set(image, 0, 0, 0, 0);
163 break;
164
165 default:
166 ASSERT_TRUE(0);
167 }
168
169 typename TestFixture::ImageTraits::PixelType zero, value;
170 TestFixture::ImageTraits::PixelTraits::SetZero(zero);
171
172 for (unsigned int y = 0; y < image.GetHeight(); y++)
173 {
174 for (unsigned int x = 0; x < image.GetWidth(); x++)
175 {
176 TestFixture::ImageTraits::GetPixel(value, image, x, y);
177 ASSERT_TRUE(TestFixture::ImageTraits::PixelTraits::IsEqual(zero, value));
178 }
179 }
180 }
181
182
183 TYPED_TEST(TestIntegerImageTraits, SetZeroFloat)
184 {
185 ImageAccessor& image = this->GetImage();
186
187 memset(image.GetBuffer(), 128, image.GetHeight() * image.GetWidth());
188
189 float c = 0.0f;
190 for (unsigned int y = 0; y < image.GetHeight(); y++)
191 {
192 for (unsigned int x = 0; x < image.GetWidth(); x++, c++)
193 {
194 TestFixture::ImageTraits::SetFloatPixel(image, c, x, y);
195 }
196 }
197
198 c = 0.0f;
199 for (unsigned int y = 0; y < image.GetHeight(); y++)
200 {
201 for (unsigned int x = 0; x < image.GetWidth(); x++, c++)
202 {
203 ASSERT_FLOAT_EQ(c, TestFixture::ImageTraits::GetFloatPixel(image, x, y));
204 }
205 }
206 }
207
208 TYPED_TEST(TestIntegerImageTraits, FillPolygon)
209 {
210 ImageAccessor& image = this->GetImage();
211
212 ImageProcessing::Set(image, 128);
213
214 // draw a triangle
215 std::vector<ImageProcessing::ImagePoint> points;
216 points.push_back(ImageProcessing::ImagePoint(1,1));
217 points.push_back(ImageProcessing::ImagePoint(1,5));
218 points.push_back(ImageProcessing::ImagePoint(5,5));
219
220 ImageProcessing::FillPolygon(image, points, 255);
221
222 // outside polygon
223 ASSERT_FLOAT_EQ(128, TestFixture::ImageTraits::GetFloatPixel(image, 0, 0));
224 ASSERT_FLOAT_EQ(128, TestFixture::ImageTraits::GetFloatPixel(image, 0, 6));
225 ASSERT_FLOAT_EQ(128, TestFixture::ImageTraits::GetFloatPixel(image, 6, 6));
226 ASSERT_FLOAT_EQ(128, TestFixture::ImageTraits::GetFloatPixel(image, 6, 0));
227
228 ASSERT_FLOAT_EQ(255, TestFixture::ImageTraits::GetFloatPixel(image, 1, 1));
229 ASSERT_FLOAT_EQ(255, TestFixture::ImageTraits::GetFloatPixel(image, 1, 2));
230 ASSERT_FLOAT_EQ(255, TestFixture::ImageTraits::GetFloatPixel(image, 1, 5));
231 ASSERT_FLOAT_EQ(255, TestFixture::ImageTraits::GetFloatPixel(image, 2, 4));
232 ASSERT_FLOAT_EQ(255, TestFixture::ImageTraits::GetFloatPixel(image, 5, 5));
233 }
234
235 TYPED_TEST(TestIntegerImageTraits, FillPolygonLargerThanImage)
236 {
237 ImageAccessor& image = this->GetImage();
238
239 ImageProcessing::Set(image, 0);
240
241 std::vector<ImageProcessing::ImagePoint> points;
242 points.push_back(ImageProcessing::ImagePoint(0, 0));
243 points.push_back(ImageProcessing::ImagePoint(image.GetWidth(),0));
244 points.push_back(ImageProcessing::ImagePoint(image.GetWidth(),image.GetHeight()));
245 points.push_back(ImageProcessing::ImagePoint(0,image.GetHeight()));
246
247 ASSERT_THROW(ImageProcessing::FillPolygon(image, points, 255), OrthancException);
248 }
249
250 TYPED_TEST(TestIntegerImageTraits, FillPolygonFullImage)
251 {
252 ImageAccessor& image = this->GetImage();
253
254 ImageProcessing::Set(image, 0);
255
256 std::vector<ImageProcessing::ImagePoint> points;
257 points.push_back(ImageProcessing::ImagePoint(0, 0));
258 points.push_back(ImageProcessing::ImagePoint(image.GetWidth() - 1,0));
259 points.push_back(ImageProcessing::ImagePoint(image.GetWidth() - 1,image.GetHeight() - 1));
260 points.push_back(ImageProcessing::ImagePoint(0,image.GetHeight() - 1));
261
262 ImageProcessing::FillPolygon(image, points, 255);
263
264 ASSERT_FLOAT_EQ(255, TestFixture::ImageTraits::GetFloatPixel(image, 0, 0));
265 ASSERT_FLOAT_EQ(255, TestFixture::ImageTraits::GetFloatPixel(image, image.GetWidth() - 1, image.GetHeight() - 1));
266 }
267
268
269
270
271 static void SetGrayscale8Pixel(ImageAccessor& image,
272 unsigned int x,
273 unsigned int y,
274 uint8_t value)
275 {
276 ImageTraits<PixelFormat_Grayscale8>::SetPixel(image, value, x, y);
277 }
278
279 static bool TestGrayscale8Pixel(const ImageAccessor& image,
280 unsigned int x,
281 unsigned int y,
282 uint8_t value)
283 {
284 PixelTraits<PixelFormat_Grayscale8>::PixelType p;
285 ImageTraits<PixelFormat_Grayscale8>::GetPixel(p, image, x, y);
286 if (p != value) printf("%d %d\n", p, value);
287 return p == value;
288 }
289
290 static void SetGrayscale16Pixel(ImageAccessor& image,
291 unsigned int x,
292 unsigned int y,
293 uint16_t value)
294 {
295 ImageTraits<PixelFormat_Grayscale16>::SetPixel(image, value, x, y);
296 }
297
298 static bool TestGrayscale16Pixel(const ImageAccessor& image,
299 unsigned int x,
300 unsigned int y,
301 uint16_t value)
302 {
303 PixelTraits<PixelFormat_Grayscale16>::PixelType p;
304 ImageTraits<PixelFormat_Grayscale16>::GetPixel(p, image, x, y);
305 if (p != value) printf("%d %d\n", p, value);
306 return p == value;
307 }
308
309 static void SetSignedGrayscale16Pixel(ImageAccessor& image,
310 unsigned int x,
311 unsigned int y,
312 int16_t value)
313 {
314 ImageTraits<PixelFormat_SignedGrayscale16>::SetPixel(image, value, x, y);
315 }
316
317 static bool TestSignedGrayscale16Pixel(const ImageAccessor& image,
318 unsigned int x,
319 unsigned int y,
320 int16_t value)
321 {
322 PixelTraits<PixelFormat_SignedGrayscale16>::PixelType p;
323 ImageTraits<PixelFormat_SignedGrayscale16>::GetPixel(p, image, x, y);
324 if (p != value) printf("%d %d\n", p, value);
325 return p == value;
326 }
327
328 static void SetRGB24Pixel(ImageAccessor& image,
329 unsigned int x,
330 unsigned int y,
331 uint8_t red,
332 uint8_t green,
333 uint8_t blue)
334 {
335 PixelTraits<PixelFormat_RGB24>::PixelType p;
336 p.red_ = red;
337 p.green_ = green;
338 p.blue_ = blue;
339 ImageTraits<PixelFormat_RGB24>::SetPixel(image, p, x, y);
340 }
341
342 static bool TestRGB24Pixel(const ImageAccessor& image,
343 unsigned int x,
344 unsigned int y,
345 uint8_t red,
346 uint8_t green,
347 uint8_t blue)
348 {
349 PixelTraits<PixelFormat_RGB24>::PixelType p;
350 ImageTraits<PixelFormat_RGB24>::GetPixel(p, image, x, y);
351 bool ok = (p.red_ == red &&
352 p.green_ == green &&
353 p.blue_ == blue);
354 if (!ok) printf("%d,%d,%d %d,%d,%d\n", p.red_, p.green_, p.blue_, red, green, blue);
355 return ok;
356 }
357
358
359 TEST(ImageProcessing, FlipGrayscale8)
360 {
361 {
362 Image image(PixelFormat_Grayscale8, 0, 0, false);
363 ImageProcessing::FlipX(image);
364 ImageProcessing::FlipY(image);
365 }
366
367 {
368 Image image(PixelFormat_Grayscale8, 1, 1, false);
369 SetGrayscale8Pixel(image, 0, 0, 128);
370 ImageProcessing::FlipX(image);
371 ImageProcessing::FlipY(image);
372 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 128));
373 }
374
375 {
376 Image image(PixelFormat_Grayscale8, 3, 2, false);
377 SetGrayscale8Pixel(image, 0, 0, 10);
378 SetGrayscale8Pixel(image, 1, 0, 20);
379 SetGrayscale8Pixel(image, 2, 0, 30);
380 SetGrayscale8Pixel(image, 0, 1, 40);
381 SetGrayscale8Pixel(image, 1, 1, 50);
382 SetGrayscale8Pixel(image, 2, 1, 60);
383
384 ImageProcessing::FlipX(image);
385 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 30));
386 ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 0, 20));
387 ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 0, 10));
388 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 1, 60));
389 ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 1, 50));
390 ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 1, 40));
391
392 ImageProcessing::FlipY(image);
393 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 60));
394 ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 0, 50));
395 ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 0, 40));
396 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 1, 30));
397 ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 1, 20));
398 ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 1, 10));
399 }
400 }
401
402
403
404 TEST(ImageProcessing, FlipRGB24)
405 {
406 Image image(PixelFormat_RGB24, 2, 2, false);
407 SetRGB24Pixel(image, 0, 0, 10, 100, 110);
408 SetRGB24Pixel(image, 1, 0, 20, 100, 110);
409 SetRGB24Pixel(image, 0, 1, 30, 100, 110);
410 SetRGB24Pixel(image, 1, 1, 40, 100, 110);
411
412 ImageProcessing::FlipX(image);
413 ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 20, 100, 110));
414 ASSERT_TRUE(TestRGB24Pixel(image, 1, 0, 10, 100, 110));
415 ASSERT_TRUE(TestRGB24Pixel(image, 0, 1, 40, 100, 110));
416 ASSERT_TRUE(TestRGB24Pixel(image, 1, 1, 30, 100, 110));
417
418 ImageProcessing::FlipY(image);
419 ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 40, 100, 110));
420 ASSERT_TRUE(TestRGB24Pixel(image, 1, 0, 30, 100, 110));
421 ASSERT_TRUE(TestRGB24Pixel(image, 0, 1, 20, 100, 110));
422 ASSERT_TRUE(TestRGB24Pixel(image, 1, 1, 10, 100, 110));
423 }
424
425
426 TEST(ImageProcessing, ResizeBasicGrayscale8)
427 {
428 Image source(PixelFormat_Grayscale8, 2, 2, false);
429 SetGrayscale8Pixel(source, 0, 0, 10);
430 SetGrayscale8Pixel(source, 1, 0, 20);
431 SetGrayscale8Pixel(source, 0, 1, 30);
432 SetGrayscale8Pixel(source, 1, 1, 40);
433
434 {
435 Image target(PixelFormat_Grayscale8, 2, 4, false);
436 ImageProcessing::Resize(target, source);
437 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 0, 10));
438 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 0, 20));
439 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 1, 10));
440 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 1, 20));
441 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 2, 30));
442 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 2, 40));
443 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 3, 30));
444 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 3, 40));
445 }
446
447 {
448 Image target(PixelFormat_Grayscale8, 4, 2, false);
449 ImageProcessing::Resize(target, source);
450 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 0, 10));
451 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 0, 10));
452 ASSERT_TRUE(TestGrayscale8Pixel(target, 2, 0, 20));
453 ASSERT_TRUE(TestGrayscale8Pixel(target, 3, 0, 20));
454 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 1, 30));
455 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 1, 30));
456 ASSERT_TRUE(TestGrayscale8Pixel(target, 2, 1, 40));
457 ASSERT_TRUE(TestGrayscale8Pixel(target, 3, 1, 40));
458 }
459 }
460
461
462 TEST(ImageProcessing, ResizeBasicRGB24)
463 {
464 Image source(PixelFormat_RGB24, 2, 2, false);
465 SetRGB24Pixel(source, 0, 0, 10, 100, 110);
466 SetRGB24Pixel(source, 1, 0, 20, 100, 110);
467 SetRGB24Pixel(source, 0, 1, 30, 100, 110);
468 SetRGB24Pixel(source, 1, 1, 40, 100, 110);
469
470 {
471 Image target(PixelFormat_RGB24, 2, 4, false);
472 ImageProcessing::Resize(target, source);
473 ASSERT_TRUE(TestRGB24Pixel(target, 0, 0, 10, 100, 110));
474 ASSERT_TRUE(TestRGB24Pixel(target, 1, 0, 20, 100, 110));
475 ASSERT_TRUE(TestRGB24Pixel(target, 0, 1, 10, 100, 110));
476 ASSERT_TRUE(TestRGB24Pixel(target, 1, 1, 20, 100, 110));
477 ASSERT_TRUE(TestRGB24Pixel(target, 0, 2, 30, 100, 110));
478 ASSERT_TRUE(TestRGB24Pixel(target, 1, 2, 40, 100, 110));
479 ASSERT_TRUE(TestRGB24Pixel(target, 0, 3, 30, 100, 110));
480 ASSERT_TRUE(TestRGB24Pixel(target, 1, 3, 40, 100, 110));
481 }
482
483 {
484 Image target(PixelFormat_RGB24, 4, 2, false);
485 ImageProcessing::Resize(target, source);
486 ASSERT_TRUE(TestRGB24Pixel(target, 0, 0, 10, 100, 110));
487 ASSERT_TRUE(TestRGB24Pixel(target, 1, 0, 10, 100, 110));
488 ASSERT_TRUE(TestRGB24Pixel(target, 2, 0, 20, 100, 110));
489 ASSERT_TRUE(TestRGB24Pixel(target, 3, 0, 20, 100, 110));
490 ASSERT_TRUE(TestRGB24Pixel(target, 0, 1, 30, 100, 110));
491 ASSERT_TRUE(TestRGB24Pixel(target, 1, 1, 30, 100, 110));
492 ASSERT_TRUE(TestRGB24Pixel(target, 2, 1, 40, 100, 110));
493 ASSERT_TRUE(TestRGB24Pixel(target, 3, 1, 40, 100, 110));
494 }
495 }
496
497
498 TEST(ImageProcessing, ResizeEmptyGrayscale8)
499 {
500 {
501 Image source(PixelFormat_Grayscale8, 0, 0, false);
502 Image target(PixelFormat_Grayscale8, 2, 2, false);
503 ImageProcessing::Resize(target, source);
504 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 0, 0));
505 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 0, 0));
506 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 1, 0));
507 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 1, 0));
508 }
509
510 {
511 Image source(PixelFormat_Grayscale8, 2, 2, false);
512 Image target(PixelFormat_Grayscale8, 0, 0, false);
513 ImageProcessing::Resize(target, source);
514 }
515 }
516
517
518 TEST(ImageProcessing, Convolution)
519 {
520 std::vector<float> k1(5, 1);
521 std::vector<float> k2(1, 1);
522
523 {
524 Image image(PixelFormat_Grayscale8, 1, 1, false);
525 SetGrayscale8Pixel(image, 0, 0, 100);
526 ImageProcessing::SeparableConvolution(image, k1, 2, k2, 0);
527 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100));
528 ImageProcessing::SeparableConvolution(image, k1, 2, k1, 2);
529 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100));
530 ImageProcessing::SeparableConvolution(image, k2, 0, k1, 2);
531 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100));
532 ImageProcessing::SeparableConvolution(image, k2, 0, k2, 0);
533 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 100));
534 }
535
536 {
537 Image image(PixelFormat_RGB24, 1, 1, false);
538 SetRGB24Pixel(image, 0, 0, 10, 20, 30);
539 ImageProcessing::SeparableConvolution(image, k1, 2, k2, 0);
540 ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30));
541 ImageProcessing::SeparableConvolution(image, k1, 2, k1, 2);
542 ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30));
543 ImageProcessing::SeparableConvolution(image, k2, 0, k1, 2);
544 ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30));
545 ImageProcessing::SeparableConvolution(image, k2, 0, k2, 0);
546 ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 10, 20, 30));
547 }
548
549 {
550 Image dirac(PixelFormat_Grayscale8, 9, 1, false);
551 ImageProcessing::Set(dirac, 0);
552 SetGrayscale8Pixel(dirac, 4, 0, 100);
553
554 {
555 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
556 ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0);
557 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0));
558 ASSERT_TRUE(TestGrayscale8Pixel(*image, 1, 0, 0));
559 ASSERT_TRUE(TestGrayscale8Pixel(*image, 2, 0, 20));
560 ASSERT_TRUE(TestGrayscale8Pixel(*image, 3, 0, 20));
561 ASSERT_TRUE(TestGrayscale8Pixel(*image, 4, 0, 20));
562 ASSERT_TRUE(TestGrayscale8Pixel(*image, 5, 0, 20));
563 ASSERT_TRUE(TestGrayscale8Pixel(*image, 6, 0, 20));
564 ASSERT_TRUE(TestGrayscale8Pixel(*image, 7, 0, 0));
565 ASSERT_TRUE(TestGrayscale8Pixel(*image, 8, 0, 0));
566 }
567
568 {
569 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
570 ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2);
571 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0));
572 ASSERT_TRUE(TestGrayscale8Pixel(*image, 1, 0, 0));
573 ASSERT_TRUE(TestGrayscale8Pixel(*image, 2, 0, 0));
574 ASSERT_TRUE(TestGrayscale8Pixel(*image, 3, 0, 0));
575 ASSERT_TRUE(TestGrayscale8Pixel(*image, 4, 0, 100));
576 ASSERT_TRUE(TestGrayscale8Pixel(*image, 5, 0, 0));
577 ASSERT_TRUE(TestGrayscale8Pixel(*image, 6, 0, 0));
578 ASSERT_TRUE(TestGrayscale8Pixel(*image, 7, 0, 0));
579 ASSERT_TRUE(TestGrayscale8Pixel(*image, 8, 0, 0));
580 }
581
582 {
583 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
584 ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0);
585 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0));
586 ASSERT_TRUE(TestGrayscale8Pixel(*image, 1, 0, 0));
587 ASSERT_TRUE(TestGrayscale8Pixel(*image, 2, 0, 0));
588 ASSERT_TRUE(TestGrayscale8Pixel(*image, 3, 0, 0));
589 ASSERT_TRUE(TestGrayscale8Pixel(*image, 4, 0, 100));
590 ASSERT_TRUE(TestGrayscale8Pixel(*image, 5, 0, 0));
591 ASSERT_TRUE(TestGrayscale8Pixel(*image, 6, 0, 0));
592 ASSERT_TRUE(TestGrayscale8Pixel(*image, 7, 0, 0));
593 ASSERT_TRUE(TestGrayscale8Pixel(*image, 8, 0, 0));
594 }
595 }
596
597 {
598 Image dirac(PixelFormat_Grayscale8, 1, 9, false);
599 ImageProcessing::Set(dirac, 0);
600 SetGrayscale8Pixel(dirac, 0, 4, 100);
601
602 {
603 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
604 ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2);
605 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0));
606 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 1, 0));
607 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 2, 20));
608 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 3, 20));
609 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 4, 20));
610 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 5, 20));
611 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 6, 20));
612 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 7, 0));
613 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 8, 0));
614 }
615
616 {
617 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
618 ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0);
619 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0));
620 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 1, 0));
621 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 2, 0));
622 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 3, 0));
623 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 4, 100));
624 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 5, 0));
625 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 6, 0));
626 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 7, 0));
627 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 8, 0));
628 }
629
630 {
631 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
632 ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0);
633 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 0, 0));
634 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 1, 0));
635 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 2, 0));
636 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 3, 0));
637 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 4, 100));
638 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 5, 0));
639 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 6, 0));
640 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 7, 0));
641 ASSERT_TRUE(TestGrayscale8Pixel(*image, 0, 8, 0));
642 }
643 }
644
645 {
646 Image dirac(PixelFormat_RGB24, 9, 1, false);
647 ImageProcessing::Set(dirac, 0);
648 SetRGB24Pixel(dirac, 4, 0, 100, 120, 140);
649
650 {
651 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
652 ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0);
653 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0));
654 ASSERT_TRUE(TestRGB24Pixel(*image, 1, 0, 0, 0, 0));
655 ASSERT_TRUE(TestRGB24Pixel(*image, 2, 0, 20, 24, 28));
656 ASSERT_TRUE(TestRGB24Pixel(*image, 3, 0, 20, 24, 28));
657 ASSERT_TRUE(TestRGB24Pixel(*image, 4, 0, 20, 24, 28));
658 ASSERT_TRUE(TestRGB24Pixel(*image, 5, 0, 20, 24, 28));
659 ASSERT_TRUE(TestRGB24Pixel(*image, 6, 0, 20, 24, 28));
660 ASSERT_TRUE(TestRGB24Pixel(*image, 7, 0, 0, 0, 0));
661 ASSERT_TRUE(TestRGB24Pixel(*image, 8, 0, 0, 0, 0));
662 }
663
664 {
665 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
666 ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2);
667 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0));
668 ASSERT_TRUE(TestRGB24Pixel(*image, 1, 0, 0, 0, 0));
669 ASSERT_TRUE(TestRGB24Pixel(*image, 2, 0, 0, 0, 0));
670 ASSERT_TRUE(TestRGB24Pixel(*image, 3, 0, 0, 0, 0));
671 ASSERT_TRUE(TestRGB24Pixel(*image, 4, 0, 100, 120, 140));
672 ASSERT_TRUE(TestRGB24Pixel(*image, 5, 0, 0, 0, 0));
673 ASSERT_TRUE(TestRGB24Pixel(*image, 6, 0, 0, 0, 0));
674 ASSERT_TRUE(TestRGB24Pixel(*image, 7, 0, 0, 0, 0));
675 ASSERT_TRUE(TestRGB24Pixel(*image, 8, 0, 0, 0, 0));
676 }
677
678 {
679 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
680 ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0);
681 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0));
682 ASSERT_TRUE(TestRGB24Pixel(*image, 1, 0, 0, 0, 0));
683 ASSERT_TRUE(TestRGB24Pixel(*image, 2, 0, 0, 0, 0));
684 ASSERT_TRUE(TestRGB24Pixel(*image, 3, 0, 0, 0, 0));
685 ASSERT_TRUE(TestRGB24Pixel(*image, 4, 0, 100, 120, 140));
686 ASSERT_TRUE(TestRGB24Pixel(*image, 5, 0, 0, 0, 0));
687 ASSERT_TRUE(TestRGB24Pixel(*image, 6, 0, 0, 0, 0));
688 ASSERT_TRUE(TestRGB24Pixel(*image, 7, 0, 0, 0, 0));
689 ASSERT_TRUE(TestRGB24Pixel(*image, 8, 0, 0, 0, 0));
690 }
691 }
692
693 {
694 Image dirac(PixelFormat_RGB24, 1, 9, false);
695 ImageProcessing::Set(dirac, 0);
696 SetRGB24Pixel(dirac, 0, 4, 100, 120, 140);
697
698 {
699 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
700 ImageProcessing::SeparableConvolution(*image, k2, 0, k1, 2);
701 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0));
702 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 1, 0, 0, 0));
703 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 2, 20, 24, 28));
704 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 3, 20, 24, 28));
705 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 4, 20, 24, 28));
706 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 5, 20, 24, 28));
707 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 6, 20, 24, 28));
708 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 7, 0, 0, 0));
709 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 8, 0, 0, 0));
710 }
711
712 {
713 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
714 ImageProcessing::SeparableConvolution(*image, k1, 2, k2, 0);
715 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0));
716 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 1, 0, 0, 0));
717 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 2, 0, 0, 0));
718 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 3, 0, 0, 0));
719 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 4, 100, 120, 140));
720 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 5, 0, 0, 0));
721 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 6, 0, 0, 0));
722 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 7, 0, 0, 0));
723 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 8, 0, 0, 0));
724 }
725
726 {
727 std::unique_ptr<ImageAccessor> image(Image::Clone(dirac));
728 ImageProcessing::SeparableConvolution(*image, k2, 0, k2, 0);
729 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 0, 0, 0, 0));
730 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 1, 0, 0, 0));
731 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 2, 0, 0, 0));
732 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 3, 0, 0, 0));
733 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 4, 100, 120, 140));
734 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 5, 0, 0, 0));
735 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 6, 0, 0, 0));
736 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 7, 0, 0, 0));
737 ASSERT_TRUE(TestRGB24Pixel(*image, 0, 8, 0, 0, 0));
738 }
739 }
740 }
741
742
743 TEST(ImageProcessing, SmoothGaussian5x5)
744 {
745 /**
746 Test the point spread function, as can be seen in Octave:
747 g1 = [ 1 4 6 4 1 ];
748 g1 /= sum(g1);
749 g2 = conv2(g1, g1');
750 floor(conv2(diag([ 0 0 100 0 0 ]), g2, 'same')) % red/green channels
751 floor(conv2(diag([ 0 0 200 0 0 ]), g2, 'same')) % blue channel
752 **/
753
754 {
755 Image image(PixelFormat_Grayscale8, 5, 5, false);
756 ImageProcessing::Set(image, 0);
757 SetGrayscale8Pixel(image, 2, 2, 100);
758 ImageProcessing::SmoothGaussian5x5(image);
759
760 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 0));
761 ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 0, 1));
762 ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 0, 2));
763 ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 0, 1));
764 ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 0, 0));
765 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 1, 1));
766 ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 1, 6));
767 ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 1, 9));
768 ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 1, 6));
769 ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 1, 1));
770 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 2, 2));
771 ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 2, 9));
772 ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 2, 14));
773 ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 2, 9));
774 ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 2, 2));
775 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 3, 1));
776 ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 3, 6));
777 ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 3, 9));
778 ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 3, 6));
779 ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 3, 1));
780 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 4, 0));
781 ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 4, 1));
782 ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 4, 2));
783 ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 4, 1));
784 ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 4, 0));
785 }
786
787 {
788 Image image(PixelFormat_RGB24, 5, 5, false);
789 ImageProcessing::Set(image, 0);
790 SetRGB24Pixel(image, 2, 2, 100, 100, 200);
791 ImageProcessing::SmoothGaussian5x5(image);
792
793 ASSERT_TRUE(TestRGB24Pixel(image, 0, 0, 0, 0, 0));
794 ASSERT_TRUE(TestRGB24Pixel(image, 1, 0, 1, 1, 3));
795 ASSERT_TRUE(TestRGB24Pixel(image, 2, 0, 2, 2, 4));
796 ASSERT_TRUE(TestRGB24Pixel(image, 3, 0, 1, 1, 3));
797 ASSERT_TRUE(TestRGB24Pixel(image, 4, 0, 0, 0, 0));
798 ASSERT_TRUE(TestRGB24Pixel(image, 0, 1, 1, 1, 3));
799 ASSERT_TRUE(TestRGB24Pixel(image, 1, 1, 6, 6, 12));
800 ASSERT_TRUE(TestRGB24Pixel(image, 2, 1, 9, 9, 18));
801 ASSERT_TRUE(TestRGB24Pixel(image, 3, 1, 6, 6, 12));
802 ASSERT_TRUE(TestRGB24Pixel(image, 4, 1, 1, 1, 3));
803 ASSERT_TRUE(TestRGB24Pixel(image, 0, 2, 2, 2, 4));
804 ASSERT_TRUE(TestRGB24Pixel(image, 1, 2, 9, 9, 18));
805 ASSERT_TRUE(TestRGB24Pixel(image, 2, 2, 14, 14, 28));
806 ASSERT_TRUE(TestRGB24Pixel(image, 3, 2, 9, 9, 18));
807 ASSERT_TRUE(TestRGB24Pixel(image, 4, 2, 2, 2, 4));
808 ASSERT_TRUE(TestRGB24Pixel(image, 0, 3, 1, 1, 3));
809 ASSERT_TRUE(TestRGB24Pixel(image, 1, 3, 6, 6, 12));
810 ASSERT_TRUE(TestRGB24Pixel(image, 2, 3, 9, 9, 18));
811 ASSERT_TRUE(TestRGB24Pixel(image, 3, 3, 6, 6, 12));
812 ASSERT_TRUE(TestRGB24Pixel(image, 4, 3, 1, 1, 3));
813 ASSERT_TRUE(TestRGB24Pixel(image, 0, 4, 0, 0, 0));
814 ASSERT_TRUE(TestRGB24Pixel(image, 1, 4, 1, 1, 3));
815 ASSERT_TRUE(TestRGB24Pixel(image, 2, 4, 2, 2, 4));
816 ASSERT_TRUE(TestRGB24Pixel(image, 3, 4, 1, 1, 3));
817 ASSERT_TRUE(TestRGB24Pixel(image, 4, 4, 0, 0, 0));
818 }
819 }
820
821 TEST(ImageProcessing, ApplyWindowingFloatToGrayScale8)
822 {
823 {
824 Image image(PixelFormat_Float32, 6, 1, false);
825 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, -5.0f, 0, 0);
826 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, 0.0f, 1, 0);
827 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, 5.0f, 2, 0);
828 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, 10.0f, 3, 0);
829 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, 1000.0f, 4, 0);
830 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, 2.0f, 5, 0);
831
832 {
833 Image target(PixelFormat_Grayscale8, 6, 1, false);
834 ImageProcessing::ApplyWindowing_Deprecated(target, image, 5.0f, 10.0f, 1.0f, 0.0f, false);
835
836 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 0, 0));
837 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 0, 0));
838 ASSERT_TRUE(TestGrayscale8Pixel(target, 2, 0, 128));
839 ASSERT_TRUE(TestGrayscale8Pixel(target, 3, 0, 255));
840 ASSERT_TRUE(TestGrayscale8Pixel(target, 4, 0, 255));
841 ASSERT_TRUE(TestGrayscale8Pixel(target, 5, 0, 255*2/10));
842 }
843
844 {
845 Image target(PixelFormat_Grayscale8, 6, 1, false);
846 ImageProcessing::ApplyWindowing_Deprecated(target, image, 5.0f, 10.0f, 1.0f, 0.0f, true);
847
848 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 0, 255));
849 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 0, 255));
850 ASSERT_TRUE(TestGrayscale8Pixel(target, 2, 0, 127));
851 ASSERT_TRUE(TestGrayscale8Pixel(target, 3, 0, 0));
852 ASSERT_TRUE(TestGrayscale8Pixel(target, 4, 0, 0));
853 ASSERT_TRUE(TestGrayscale8Pixel(target, 5, 0, 255 - 255*2/10));
854 }
855
856 {
857 Image target(PixelFormat_Grayscale8, 6, 1, false);
858 ImageProcessing::ApplyWindowing_Deprecated(target, image, 5000.0f, 10000.01f, 1000.0f, 0.0f, false);
859
860 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 0, 0));
861 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 0, 0));
862 ASSERT_TRUE(TestGrayscale8Pixel(target, 2, 0, 128));
863 ASSERT_TRUE(TestGrayscale8Pixel(target, 3, 0, 255));
864 ASSERT_TRUE(TestGrayscale8Pixel(target, 4, 0, 255));
865 ASSERT_TRUE(TestGrayscale8Pixel(target, 5, 0, 255*2/10));
866 }
867
868 {
869 Image target(PixelFormat_Grayscale8, 6, 1, false);
870 ImageProcessing::ApplyWindowing_Deprecated(target, image, 5000.0f, 10000.01f, 1000.0f, 0.0f, true);
871
872 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 0, 255));
873 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 0, 255));
874 ASSERT_TRUE(TestGrayscale8Pixel(target, 2, 0, 127));
875 ASSERT_TRUE(TestGrayscale8Pixel(target, 3, 0, 0));
876 ASSERT_TRUE(TestGrayscale8Pixel(target, 4, 0, 0));
877 ASSERT_TRUE(TestGrayscale8Pixel(target, 5, 0, 255 - 256*2/10));
878 }
879
880 {
881 Image target(PixelFormat_Grayscale8, 6, 1, false);
882 ImageProcessing::ApplyWindowing_Deprecated(target, image, 50.0f, 100.1f, 10.0f, 30.0f, false);
883
884 ASSERT_TRUE(TestGrayscale8Pixel(target, 0, 0, 0)); // (-5 * 10) + 30 => pixel value = -20 => 0
885 ASSERT_TRUE(TestGrayscale8Pixel(target, 1, 0, 256*30/100)); // ((0 * 10) + 30 => pixel value = 30 => 30%
886 ASSERT_TRUE(TestGrayscale8Pixel(target, 2, 0, 256*80/100)); // ((5 * 10) + 30 => pixel value = 80 => 80%
887 ASSERT_TRUE(TestGrayscale8Pixel(target, 3, 0, 255)); // ((10 * 10) + 30 => pixel value = 130 => 100%
888 ASSERT_TRUE(TestGrayscale8Pixel(target, 4, 0, 255)); // ((1000 * 10) + 30 => pixel value = 10030 => 100%
889 ASSERT_TRUE(TestGrayscale8Pixel(target, 5, 0, 128)); // ((2 * 10) + 30 => pixel value = 50 => 50%
890 }
891
892 }
893 }
894
895 TEST(ImageProcessing, ApplyWindowingFloatToGrayScale16)
896 {
897 {
898 Image image(PixelFormat_Float32, 6, 1, false);
899 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, -5.0f, 0, 0);
900 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, 0.0f, 1, 0);
901 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, 5.0f, 2, 0);
902 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, 10.0f, 3, 0);
903 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, 1000.0f, 4, 0);
904 ImageTraits<PixelFormat_Float32>::SetFloatPixel(image, 2.0f, 5, 0);
905
906 {
907 Image target(PixelFormat_Grayscale16, 6, 1, false);
908 ImageProcessing::ApplyWindowing_Deprecated(target, image, 5.0f, 10.0f, 1.0f, 0.0f, false);
909
910 ASSERT_TRUE(TestGrayscale16Pixel(target, 0, 0, 0));
911 ASSERT_TRUE(TestGrayscale16Pixel(target, 1, 0, 0));
912 ASSERT_TRUE(TestGrayscale16Pixel(target, 2, 0, 32768));
913 ASSERT_TRUE(TestGrayscale16Pixel(target, 3, 0, 65535));
914 ASSERT_TRUE(TestGrayscale16Pixel(target, 4, 0, 65535));
915 ASSERT_TRUE(TestGrayscale16Pixel(target, 5, 0, 65536*2/10));
916 }
917 }
918 }
919
920 TEST(ImageProcessing, ApplyWindowingGrayScale8ToGrayScale16)
921 {
922 {
923 Image image(PixelFormat_Grayscale8, 5, 1, false);
924 SetGrayscale8Pixel(image, 0, 0, 0);
925 SetGrayscale8Pixel(image, 1, 0, 2);
926 SetGrayscale8Pixel(image, 2, 0, 5);
927 SetGrayscale8Pixel(image, 3, 0, 10);
928 SetGrayscale8Pixel(image, 4, 0, 255);
929
930 {
931 Image target(PixelFormat_Grayscale16, 5, 1, false);
932 ImageProcessing::ApplyWindowing_Deprecated(target, image, 5.0f, 10.0f, 1.0f, 0.0f, false);
933
934 ASSERT_TRUE(TestGrayscale16Pixel(target, 0, 0, 0));
935 ASSERT_TRUE(TestGrayscale16Pixel(target, 1, 0, 65536*2/10));
936 ASSERT_TRUE(TestGrayscale16Pixel(target, 2, 0, 65536*5/10));
937 ASSERT_TRUE(TestGrayscale16Pixel(target, 3, 0, 65535));
938 ASSERT_TRUE(TestGrayscale16Pixel(target, 4, 0, 65535));
939 }
940 }
941 }
942
943 TEST(ImageProcessing, ApplyWindowingGrayScale16ToGrayScale16)
944 {
945 {
946 Image image(PixelFormat_Grayscale16, 5, 1, false);
947 SetGrayscale16Pixel(image, 0, 0, 0);
948 SetGrayscale16Pixel(image, 1, 0, 2);
949 SetGrayscale16Pixel(image, 2, 0, 5);
950 SetGrayscale16Pixel(image, 3, 0, 10);
951 SetGrayscale16Pixel(image, 4, 0, 255);
952
953 {
954 Image target(PixelFormat_Grayscale16, 5, 1, false);
955 ImageProcessing::ApplyWindowing_Deprecated(target, image, 5.0f, 10.0f, 1.0f, 0.0f, false);
956
957 ASSERT_TRUE(TestGrayscale16Pixel(target, 0, 0, 0));
958 ASSERT_TRUE(TestGrayscale16Pixel(target, 1, 0, 65536*2/10));
959 ASSERT_TRUE(TestGrayscale16Pixel(target, 2, 0, 65536*5/10));
960 ASSERT_TRUE(TestGrayscale16Pixel(target, 3, 0, 65535));
961 ASSERT_TRUE(TestGrayscale16Pixel(target, 4, 0, 65535));
962 }
963 }
964 }
965
966
967 TEST(ImageProcessing, ShiftScaleGrayscale8)
968 {
969 Image image(PixelFormat_Grayscale8, 5, 1, false);
970 SetGrayscale8Pixel(image, 0, 0, 0);
971 SetGrayscale8Pixel(image, 1, 0, 2);
972 SetGrayscale8Pixel(image, 2, 0, 5);
973 SetGrayscale8Pixel(image, 3, 0, 10);
974 SetGrayscale8Pixel(image, 4, 0, 255);
975
976 ImageProcessing::ShiftScale(image, -1.1, 1.5, true);
977 ASSERT_TRUE(TestGrayscale8Pixel(image, 0, 0, 0));
978 ASSERT_TRUE(TestGrayscale8Pixel(image, 1, 0, 1));
979 ASSERT_TRUE(TestGrayscale8Pixel(image, 2, 0, 6));
980 ASSERT_TRUE(TestGrayscale8Pixel(image, 3, 0, 13));
981 ASSERT_TRUE(TestGrayscale8Pixel(image, 4, 0, 255));
982 }
983
984
985 TEST(ImageProcessing, ShiftScaleGrayscale16)
986 {
987 Image image(PixelFormat_Grayscale16, 5, 1, false);
988 SetGrayscale16Pixel(image, 0, 0, 0);
989 SetGrayscale16Pixel(image, 1, 0, 2);
990 SetGrayscale16Pixel(image, 2, 0, 5);
991 SetGrayscale16Pixel(image, 3, 0, 10);
992 SetGrayscale16Pixel(image, 4, 0, 255);
993
994 ImageProcessing::ShiftScale(image, -1.1, 1.5, true);
995 ASSERT_TRUE(TestGrayscale16Pixel(image, 0, 0, 0));
996 ASSERT_TRUE(TestGrayscale16Pixel(image, 1, 0, 1));
997 ASSERT_TRUE(TestGrayscale16Pixel(image, 2, 0, 6));
998 ASSERT_TRUE(TestGrayscale16Pixel(image, 3, 0, 13));
999 ASSERT_TRUE(TestGrayscale16Pixel(image, 4, 0, 381));
1000 }
1001
1002
1003 TEST(ImageProcessing, ShiftScaleSignedGrayscale16)
1004 {
1005 Image image(PixelFormat_SignedGrayscale16, 5, 1, false);
1006 SetSignedGrayscale16Pixel(image, 0, 0, 0);
1007 SetSignedGrayscale16Pixel(image, 1, 0, 2);
1008 SetSignedGrayscale16Pixel(image, 2, 0, 5);
1009 SetSignedGrayscale16Pixel(image, 3, 0, 10);
1010 SetSignedGrayscale16Pixel(image, 4, 0, 255);
1011
1012 ImageProcessing::ShiftScale(image, -17.1, 11.5, true);
1013 ASSERT_TRUE(TestSignedGrayscale16Pixel(image, 0, 0, -197));
1014 ASSERT_TRUE(TestSignedGrayscale16Pixel(image, 1, 0, -174));
1015 ASSERT_TRUE(TestSignedGrayscale16Pixel(image, 2, 0, -139));
1016 ASSERT_TRUE(TestSignedGrayscale16Pixel(image, 3, 0, -82));
1017 ASSERT_TRUE(TestSignedGrayscale16Pixel(image, 4, 0, 2736));
1018 }