comparison OrthancFramework/UnitTestsSources/ImageTests.cpp @ 4046:7ff1e6c80627 framework

moving ImageTests.cpp to framework
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 10 Jun 2020 21:43:31 +0200
parents OrthancServer/UnitTestsSources/ImageTests.cpp@05b8fd21089c
children 0953b3dc3261
comparison
equal deleted inserted replaced
4045:05b8fd21089c 4046:7ff1e6c80627
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 "gtest/gtest.h"
39
40 #include "../Sources/Images/Font.h"
41 #include "../Sources/Images/Image.h"
42 #include "../Sources/Images/ImageProcessing.h"
43 #include "../Sources/Images/JpegReader.h"
44 #include "../Sources/Images/JpegWriter.h"
45 #include "../Sources/Images/PngReader.h"
46 #include "../Sources/Images/PngWriter.h"
47 #include "../Sources/Images/PamReader.h"
48 #include "../Sources/Images/PamWriter.h"
49 #include "../Sources/SystemToolbox.h"
50 #include "../Sources/Toolbox.h"
51 #include "../Sources/TemporaryFile.h"
52
53 #include <stdint.h>
54
55
56 TEST(PngWriter, ColorPattern)
57 {
58 Orthanc::PngWriter w;
59 unsigned int width = 17;
60 unsigned int height = 61;
61 unsigned int pitch = width * 3;
62
63 std::vector<uint8_t> image(height * pitch);
64 for (unsigned int y = 0; y < height; y++)
65 {
66 uint8_t *p = &image[0] + y * pitch;
67 for (unsigned int x = 0; x < width; x++, p += 3)
68 {
69 p[0] = (y % 3 == 0) ? 255 : 0;
70 p[1] = (y % 3 == 1) ? 255 : 0;
71 p[2] = (y % 3 == 2) ? 255 : 0;
72 }
73 }
74
75 Orthanc::ImageAccessor accessor;
76 accessor.AssignReadOnly(Orthanc::PixelFormat_RGB24, width, height, pitch, &image[0]);
77
78 w.WriteToFile("UnitTestsResults/ColorPattern.png", accessor);
79
80 std::string f, md5;
81 Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/ColorPattern.png");
82 Orthanc::Toolbox::ComputeMD5(md5, f);
83 ASSERT_EQ("604e785f53c99cae6ea4584870b2c41d", md5);
84 }
85
86 TEST(PngWriter, Gray8Pattern)
87 {
88 Orthanc::PngWriter w;
89 int width = 17;
90 int height = 256;
91 int pitch = width;
92
93 std::vector<uint8_t> image(height * pitch);
94 for (int y = 0; y < height; y++)
95 {
96 uint8_t *p = &image[0] + y * pitch;
97 for (int x = 0; x < width; x++, p++)
98 {
99 *p = y;
100 }
101 }
102
103 Orthanc::ImageAccessor accessor;
104 accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale8, width, height, pitch, &image[0]);
105
106 w.WriteToFile("UnitTestsResults/Gray8Pattern.png", accessor);
107
108 std::string f, md5;
109 Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/Gray8Pattern.png");
110 Orthanc::Toolbox::ComputeMD5(md5, f);
111 ASSERT_EQ("5a9b98bea3d0a6d983980cc38bfbcdb3", md5);
112 }
113
114 TEST(PngWriter, Gray16Pattern)
115 {
116 Orthanc::PngWriter w;
117 int width = 256;
118 int height = 256;
119 int pitch = width * 2 + 16;
120
121 std::vector<uint8_t> image(height * pitch);
122
123 int v = 0;
124 for (int y = 0; y < height; y++)
125 {
126 uint16_t *p = reinterpret_cast<uint16_t*>(&image[0] + y * pitch);
127 for (int x = 0; x < width; x++, p++, v++)
128 {
129 *p = v;
130 }
131 }
132
133 Orthanc::ImageAccessor accessor;
134 accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale16, width, height, pitch, &image[0]);
135 w.WriteToFile("UnitTestsResults/Gray16Pattern.png", accessor);
136
137 std::string f, md5;
138 Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/Gray16Pattern.png");
139 Orthanc::Toolbox::ComputeMD5(md5, f);
140 ASSERT_EQ("0785866a08bf0a02d2eeff87f658571c", md5);
141 }
142
143 TEST(PngWriter, EndToEnd)
144 {
145 Orthanc::PngWriter w;
146 unsigned int width = 256;
147 unsigned int height = 256;
148 unsigned int pitch = width * 2 + 16;
149
150 std::vector<uint8_t> image(height * pitch);
151
152 int v = 0;
153 for (unsigned int y = 0; y < height; y++)
154 {
155 uint16_t *p = reinterpret_cast<uint16_t*>(&image[0] + y * pitch);
156 for (unsigned int x = 0; x < width; x++, p++, v++)
157 {
158 *p = v;
159 }
160 }
161
162 Orthanc::ImageAccessor accessor;
163 accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale16, width, height, pitch, &image[0]);
164
165 std::string s;
166 w.WriteToMemory(s, accessor);
167
168 {
169 Orthanc::PngReader r;
170 r.ReadFromMemory(s);
171
172 ASSERT_EQ(r.GetFormat(), Orthanc::PixelFormat_Grayscale16);
173 ASSERT_EQ(r.GetWidth(), width);
174 ASSERT_EQ(r.GetHeight(), height);
175
176 v = 0;
177 for (unsigned int y = 0; y < height; y++)
178 {
179 const uint16_t *p = reinterpret_cast<const uint16_t*>((const uint8_t*) r.GetConstBuffer() + y * r.GetPitch());
180 ASSERT_EQ(p, r.GetConstRow(y));
181 for (unsigned int x = 0; x < width; x++, p++, v++)
182 {
183 ASSERT_EQ(*p, v);
184 }
185 }
186 }
187
188 {
189 Orthanc::TemporaryFile tmp;
190 tmp.Write(s);
191
192 Orthanc::PngReader r2;
193 r2.ReadFromFile(tmp.GetPath());
194
195 ASSERT_EQ(r2.GetFormat(), Orthanc::PixelFormat_Grayscale16);
196 ASSERT_EQ(r2.GetWidth(), width);
197 ASSERT_EQ(r2.GetHeight(), height);
198
199 v = 0;
200 for (unsigned int y = 0; y < height; y++)
201 {
202 const uint16_t *p = reinterpret_cast<const uint16_t*>((const uint8_t*) r2.GetConstBuffer() + y * r2.GetPitch());
203 ASSERT_EQ(p, r2.GetConstRow(y));
204 for (unsigned int x = 0; x < width; x++, p++, v++)
205 {
206 ASSERT_EQ(*p, v);
207 }
208 }
209 }
210 }
211
212
213
214
215 TEST(JpegWriter, Basic)
216 {
217 std::string s;
218
219 {
220 Orthanc::Image img(Orthanc::PixelFormat_Grayscale8, 16, 16, false);
221 for (unsigned int y = 0, value = 0; y < img.GetHeight(); y++)
222 {
223 uint8_t* p = reinterpret_cast<uint8_t*>(img.GetRow(y));
224 for (unsigned int x = 0; x < img.GetWidth(); x++, p++)
225 {
226 *p = value++;
227 }
228 }
229
230 Orthanc::JpegWriter w;
231 w.WriteToFile("UnitTestsResults/hello.jpg", img);
232
233 w.WriteToMemory(s, img);
234 Orthanc::SystemToolbox::WriteFile(s, "UnitTestsResults/hello2.jpg");
235
236 std::string t;
237 Orthanc::SystemToolbox::ReadFile(t, "UnitTestsResults/hello.jpg");
238 ASSERT_EQ(s.size(), t.size());
239 ASSERT_EQ(0, memcmp(s.c_str(), t.c_str(), s.size()));
240 }
241
242 {
243 Orthanc::JpegReader r1, r2;
244 r1.ReadFromFile("UnitTestsResults/hello.jpg");
245 ASSERT_EQ(16u, r1.GetWidth());
246 ASSERT_EQ(16u, r1.GetHeight());
247
248 r2.ReadFromMemory(s);
249 ASSERT_EQ(16u, r2.GetWidth());
250 ASSERT_EQ(16u, r2.GetHeight());
251
252 for (unsigned int y = 0; y < r1.GetHeight(); y++)
253 {
254 const uint8_t* p1 = reinterpret_cast<const uint8_t*>(r1.GetConstRow(y));
255 const uint8_t* p2 = reinterpret_cast<const uint8_t*>(r2.GetConstRow(y));
256 for (unsigned int x = 0; x < r1.GetWidth(); x++)
257 {
258 ASSERT_EQ(*p1, *p2);
259 }
260 }
261 }
262 }
263
264
265 TEST(PamWriter, ColorPattern)
266 {
267 Orthanc::PamWriter w;
268 unsigned int width = 17;
269 unsigned int height = 61;
270 unsigned int pitch = width * 3;
271
272 std::vector<uint8_t> image(height * pitch);
273 for (unsigned int y = 0; y < height; y++)
274 {
275 uint8_t *p = &image[0] + y * pitch;
276 for (unsigned int x = 0; x < width; x++, p += 3)
277 {
278 p[0] = (y % 3 == 0) ? 255 : 0;
279 p[1] = (y % 3 == 1) ? 255 : 0;
280 p[2] = (y % 3 == 2) ? 255 : 0;
281 }
282 }
283
284 Orthanc::ImageAccessor accessor;
285 accessor.AssignReadOnly(Orthanc::PixelFormat_RGB24, width, height, pitch, &image[0]);
286
287 w.WriteToFile("UnitTestsResults/ColorPattern.pam", accessor);
288
289 std::string f, md5;
290 Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/ColorPattern.pam");
291 Orthanc::Toolbox::ComputeMD5(md5, f);
292 ASSERT_EQ("81a3441754e88969ebbe53e69891e841", md5);
293 }
294
295 TEST(PamWriter, Gray8Pattern)
296 {
297 Orthanc::PamWriter w;
298 int width = 17;
299 int height = 256;
300 int pitch = width;
301
302 std::vector<uint8_t> image(height * pitch);
303 for (int y = 0; y < height; y++)
304 {
305 uint8_t *p = &image[0] + y * pitch;
306 for (int x = 0; x < width; x++, p++)
307 {
308 *p = y;
309 }
310 }
311
312 Orthanc::ImageAccessor accessor;
313 accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale8, width, height, pitch, &image[0]);
314
315 w.WriteToFile("UnitTestsResults/Gray8Pattern.pam", accessor);
316
317 std::string f, md5;
318 Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/Gray8Pattern.pam");
319 Orthanc::Toolbox::ComputeMD5(md5, f);
320 ASSERT_EQ("7873c408d26a9d11dd1c1de5e69cc0a3", md5);
321 }
322
323 TEST(PamWriter, Gray16Pattern)
324 {
325 Orthanc::PamWriter w;
326 int width = 256;
327 int height = 256;
328 int pitch = width * 2 + 16;
329
330 std::vector<uint8_t> image(height * pitch);
331
332 int v = 0;
333 for (int y = 0; y < height; y++)
334 {
335 uint16_t *p = reinterpret_cast<uint16_t*>(&image[0] + y * pitch);
336 for (int x = 0; x < width; x++, p++, v++)
337 {
338 *p = v;
339 }
340 }
341
342 Orthanc::ImageAccessor accessor;
343 accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale16, width, height, pitch, &image[0]);
344 w.WriteToFile("UnitTestsResults/Gray16Pattern.pam", accessor);
345
346 std::string f, md5;
347 Orthanc::SystemToolbox::ReadFile(f, "UnitTestsResults/Gray16Pattern.pam");
348 Orthanc::Toolbox::ComputeMD5(md5, f);
349 ASSERT_EQ("b268772bf28f3b2b8520ff21c5e3dcb6", md5);
350 }
351
352 TEST(PamWriter, EndToEnd)
353 {
354 Orthanc::PamWriter w;
355 unsigned int width = 256;
356 unsigned int height = 256;
357 unsigned int pitch = width * 2 + 16;
358
359 std::vector<uint8_t> image(height * pitch);
360
361 int v = 0;
362 for (unsigned int y = 0; y < height; y++)
363 {
364 uint16_t *p = reinterpret_cast<uint16_t*>(&image[0] + y * pitch);
365 for (unsigned int x = 0; x < width; x++, p++, v++)
366 {
367 *p = v;
368 }
369 }
370
371 Orthanc::ImageAccessor accessor;
372 accessor.AssignReadOnly(Orthanc::PixelFormat_Grayscale16, width, height, pitch, &image[0]);
373
374 std::string s;
375 w.WriteToMemory(s, accessor);
376
377 {
378 Orthanc::PamReader r;
379 r.ReadFromMemory(s);
380
381 ASSERT_EQ(r.GetFormat(), Orthanc::PixelFormat_Grayscale16);
382 ASSERT_EQ(r.GetWidth(), width);
383 ASSERT_EQ(r.GetHeight(), height);
384
385 v = 0;
386 for (unsigned int y = 0; y < height; y++)
387 {
388 const uint16_t *p = reinterpret_cast<const uint16_t*>
389 ((const uint8_t*) r.GetConstBuffer() + y * r.GetPitch());
390 ASSERT_EQ(p, r.GetConstRow(y));
391 for (unsigned int x = 0; x < width; x++, p++, v++)
392 {
393 ASSERT_EQ(v, *p);
394 }
395 }
396 }
397
398 {
399 // true means "enforce alignment by using a temporary buffer"
400 Orthanc::PamReader r(true);
401 r.ReadFromMemory(s);
402
403 ASSERT_EQ(r.GetFormat(), Orthanc::PixelFormat_Grayscale16);
404 ASSERT_EQ(r.GetWidth(), width);
405 ASSERT_EQ(r.GetHeight(), height);
406
407 v = 0;
408 for (unsigned int y = 0; y < height; y++)
409 {
410 const uint16_t* p = reinterpret_cast<const uint16_t*>
411 ((const uint8_t*)r.GetConstBuffer() + y * r.GetPitch());
412 ASSERT_EQ(p, r.GetConstRow(y));
413 for (unsigned int x = 0; x < width; x++, p++, v++)
414 {
415 ASSERT_EQ(v, *p);
416 }
417 }
418 }
419
420 {
421 Orthanc::TemporaryFile tmp;
422 tmp.Write(s);
423
424 Orthanc::PamReader r2;
425 r2.ReadFromFile(tmp.GetPath());
426
427 ASSERT_EQ(r2.GetFormat(), Orthanc::PixelFormat_Grayscale16);
428 ASSERT_EQ(r2.GetWidth(), width);
429 ASSERT_EQ(r2.GetHeight(), height);
430
431 v = 0;
432 for (unsigned int y = 0; y < height; y++)
433 {
434 const uint16_t *p = reinterpret_cast<const uint16_t*>
435 ((const uint8_t*) r2.GetConstBuffer() + y * r2.GetPitch());
436 ASSERT_EQ(p, r2.GetConstRow(y));
437 for (unsigned int x = 0; x < width; x++, p++, v++)
438 {
439 ASSERT_EQ(*p, v);
440 }
441 }
442 }
443
444 {
445 Orthanc::TemporaryFile tmp;
446 tmp.Write(s);
447
448 // true means "enforce alignment by using a temporary buffer"
449 Orthanc::PamReader r2(true);
450 r2.ReadFromFile(tmp.GetPath());
451
452 ASSERT_EQ(r2.GetFormat(), Orthanc::PixelFormat_Grayscale16);
453 ASSERT_EQ(r2.GetWidth(), width);
454 ASSERT_EQ(r2.GetHeight(), height);
455
456 v = 0;
457 for (unsigned int y = 0; y < height; y++)
458 {
459 const uint16_t* p = reinterpret_cast<const uint16_t*>
460 ((const uint8_t*)r2.GetConstBuffer() + y * r2.GetPitch());
461 ASSERT_EQ(p, r2.GetConstRow(y));
462 for (unsigned int x = 0; x < width; x++, p++, v++)
463 {
464 ASSERT_EQ(*p, v);
465 }
466 }
467 }
468
469 }