Mercurial > hg > orthanc-wsi
annotate Framework/Inputs/OpenSlidePyramid.cpp @ 318:8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 11 Sep 2024 16:11:16 +0200 |
parents | f611fb47d0e8 |
children | 0c34b6625c67 |
rev | line source |
---|---|
0 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
312
0683312e21ba
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
309
diff
changeset
|
5 * Copyright (C) 2017-2023 Osimis S.A., Belgium |
0683312e21ba
updated copyright, as Orthanc Team now replaces Osimis
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
309
diff
changeset
|
6 * Copyright (C) 2024-2024 Orthanc Team SRL, Belgium |
309
7020852a8fa9
updated year to 2024
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
279
diff
changeset
|
7 * Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium |
0 | 8 * |
9 * This program is free software: you can redistribute it and/or | |
10 * modify it under the terms of the GNU Affero General Public License | |
11 * as published by the Free Software Foundation, either version 3 of | |
12 * the License, or (at your option) any later version. | |
13 * | |
14 * This program is distributed in the hope that it will be useful, but | |
15 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 * Affero General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU Affero General Public License | |
20 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
21 **/ | |
22 | |
23 | |
16
7a88c614be04
preparing for precompiled headers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
24 #include "../PrecompiledHeadersWSI.h" |
0 | 25 #include "OpenSlidePyramid.h" |
26 | |
199
a1c265cb2174
replacing deprecated std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
192
diff
changeset
|
27 #include <Compatibility.h> // For std::unique_ptr |
192 | 28 #include <Images/ImageProcessing.h> |
29 #include <OrthancException.h> | |
279
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
30 #include <SerializationToolbox.h> |
192 | 31 #include <Logging.h> |
140
a0f9a3df1110
resort to Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
115
diff
changeset
|
32 |
315
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
33 #include <boost/math/special_functions/round.hpp> |
140
a0f9a3df1110
resort to Orthanc framework
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
115
diff
changeset
|
34 #include <memory> |
0 | 35 |
36 namespace OrthancWSI | |
37 { | |
38 void OpenSlidePyramid::ReadRegion(Orthanc::ImageAccessor& target, | |
318
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
39 bool& isEmpty, |
0 | 40 unsigned int level, |
41 unsigned int x, | |
42 unsigned int y) | |
43 { | |
199
a1c265cb2174
replacing deprecated std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
192
diff
changeset
|
44 std::unique_ptr<Orthanc::ImageAccessor> source(image_.ReadRegion(level, x, y, target.GetWidth(), target.GetHeight())); |
315
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
45 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
46 if (target.GetWidth() != source->GetWidth() || |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
47 target.GetHeight() != source->GetHeight()) |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
48 { |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
49 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
50 } |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
51 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
52 const unsigned int width = source->GetWidth(); |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
53 const unsigned int height = source->GetHeight(); |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
54 |
318
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
55 if (source->GetFormat() == Orthanc::PixelFormat_BGRA32) |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
56 { |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
57 isEmpty = true; |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
58 |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
59 for (unsigned int y = 0; y < height && isEmpty; y++) |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
60 { |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
61 const uint8_t* p = reinterpret_cast<const uint8_t*>(source->GetConstRow(y)); |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
62 for (unsigned int x = 0; x < width && isEmpty; x++) |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
63 { |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
64 if (p[3] != 0) |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
65 { |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
66 isEmpty = false; |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
67 } |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
68 |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
69 p += 4; |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
70 } |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
71 } |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
72 } |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
73 else |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
74 { |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
75 isEmpty = false; |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
76 } |
8ad12abde290
sparse re-encoding with OpenSlide (notably for MIRAX format)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
317
diff
changeset
|
77 |
315
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
78 if (target.GetFormat() == Orthanc::PixelFormat_RGB24 && |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
79 source->GetFormat() == Orthanc::PixelFormat_BGRA32) |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
80 { |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
81 // Implements alpha blending: https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending |
317
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
82 |
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
83 uint8_t backgroundRed, backgroundGreen, backgroundBlue; |
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
84 GetBackgroundColor(backgroundRed, backgroundGreen, backgroundBlue); |
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
85 |
315
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
86 for (unsigned int y = 0; y < height; y++) |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
87 { |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
88 const uint8_t* p = reinterpret_cast<const uint8_t*>(source->GetConstRow(y)); |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
89 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
90 for (unsigned int x = 0; x < width; x++) |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
91 { |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
92 /** |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
93 Alpha blending using integer arithmetics only (16 bits avoids overflows) |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
94 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
95 p = (1 - alpha) * background + alpha * value |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
96 <=> p = (1 - p[3] / 255) * background + p[3] / 255 * value |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
97 <=> p = ((255 - p[3]) * background + p[3] * value) / 255 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
98 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
99 **/ |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
100 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
101 uint16_t alpha = p[3]; |
317
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
102 q[0] = static_cast<uint8_t>(((255 - alpha) * backgroundRed + alpha * p[2]) / 255); |
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
103 q[1] = static_cast<uint8_t>(((255 - alpha) * backgroundGreen + alpha * p[1]) / 255); |
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
104 q[2] = static_cast<uint8_t>(((255 - alpha) * backgroundBlue + alpha * p[0]) / 255); |
315
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
105 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
106 p += 4; |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
107 q += 3; |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
108 } |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
109 } |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
110 } |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
111 else |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
112 { |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
113 Orthanc::ImageProcessing::Convert(target, *source); |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
114 } |
0 | 115 } |
116 | |
117 | |
118 OpenSlidePyramid::OpenSlidePyramid(const std::string& path, | |
119 unsigned int tileWidth, | |
120 unsigned int tileHeight) : | |
121 image_(path), | |
122 tileWidth_(tileWidth), | |
123 tileHeight_(tileHeight) | |
124 { | |
125 } | |
279
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
126 |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
127 |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
128 bool OpenSlidePyramid::LookupImagedVolumeSize(float& width, |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
129 float& height) const |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
130 { |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
131 std::string s; |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
132 double mppx; |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
133 double mppy; |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
134 |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
135 if (image_.LookupProperty(s, "openslide.mpp-x") && |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
136 Orthanc::SerializationToolbox::ParseDouble(mppx, s) && |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
137 image_.LookupProperty(s, "openslide.mpp-y") && |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
138 Orthanc::SerializationToolbox::ParseDouble(mppy, s)) |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
139 { |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
140 // In the 2 lines below, remember to switch X/Y when going from physical to pixel coordinates! |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
141 width = mppy / 1000.0 * static_cast<double>(image_.GetLevelHeight(0)); |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
142 height = mppx / 1000.0 * static_cast<double>(image_.GetLevelWidth(0)); |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
143 return true; |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
144 } |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
145 else |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
146 { |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
147 return false; |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
148 } |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
149 } |
0 | 150 } |