Mercurial > hg > orthanc
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 } |