Mercurial > hg > orthanc-wsi
annotate Framework/Inputs/OpenSlidePyramid.cpp @ 329:ae2d769215d2
refactoring
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 18 Oct 2024 08:48:53 +0200 |
parents | 0c34b6625c67 |
children |
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 { | |
329 | 38 // Test whether the full alpha channel (if any) equals 255 |
39 static bool IsFullyTransparent(const Orthanc::ImageAccessor& source) | |
40 { | |
41 if (source.GetFormat() == Orthanc::PixelFormat_BGRA32 || | |
42 source.GetFormat() == Orthanc::PixelFormat_RGBA32) | |
43 { | |
44 const unsigned int width = source.GetWidth(); | |
45 const unsigned int height = source.GetHeight(); | |
46 | |
47 bool isEmpty = true; | |
48 | |
49 for (unsigned int yy = 0; yy < height && isEmpty; yy++) | |
50 { | |
51 const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(yy)); | |
52 for (unsigned int xx = 0; xx < width && isEmpty; xx++) | |
53 { | |
54 if (p[3] != 0) | |
55 { | |
56 isEmpty = false; | |
57 } | |
58 | |
59 p += 4; | |
60 } | |
61 } | |
62 | |
63 return isEmpty; | |
64 } | |
65 else | |
66 { | |
67 return false; | |
68 } | |
69 } | |
70 | |
71 | |
0 | 72 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
|
73 bool& isEmpty, |
0 | 74 unsigned int level, |
75 unsigned int x, | |
76 unsigned int y) | |
77 { | |
199
a1c265cb2174
replacing deprecated std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
192
diff
changeset
|
78 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
|
79 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
80 if (target.GetWidth() != source->GetWidth() || |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
81 target.GetHeight() != source->GetHeight()) |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
82 { |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
83 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
84 } |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
85 |
329 | 86 isEmpty = IsFullyTransparent(*source); |
87 | |
315
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
88 const unsigned int width = source->GetWidth(); |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
89 const unsigned int height = source->GetHeight(); |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
90 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
91 if (target.GetFormat() == Orthanc::PixelFormat_RGB24 && |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
92 source->GetFormat() == Orthanc::PixelFormat_BGRA32) |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
93 { |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
94 // 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
|
95 |
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
96 uint8_t backgroundRed, backgroundGreen, backgroundBlue; |
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
97 GetBackgroundColor(backgroundRed, backgroundGreen, backgroundBlue); |
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
98 |
321 | 99 for (unsigned int yy = 0; yy < height; yy++) |
315
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
100 { |
321 | 101 const uint8_t* p = reinterpret_cast<const uint8_t*>(source->GetConstRow(yy)); |
102 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(yy)); | |
103 for (unsigned int xx = 0; xx < width; xx++) | |
315
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
104 { |
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 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
|
107 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
108 p = (1 - alpha) * background + alpha * value |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
109 <=> 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
|
110 <=> 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
|
111 |
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 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
114 uint16_t alpha = p[3]; |
317
f611fb47d0e8
reuse base class members in OpenSlidePyramid
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
315
diff
changeset
|
115 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
|
116 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
|
117 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
|
118 |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
119 p += 4; |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
120 q += 3; |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
121 } |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
122 } |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
123 } |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
124 else |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
125 { |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
126 Orthanc::ImageProcessing::Convert(target, *source); |
072968f00d26
support of transparency in OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
312
diff
changeset
|
127 } |
0 | 128 } |
129 | |
130 | |
131 OpenSlidePyramid::OpenSlidePyramid(const std::string& path, | |
132 unsigned int tileWidth, | |
133 unsigned int tileHeight) : | |
134 image_(path), | |
135 tileWidth_(tileWidth), | |
136 tileHeight_(tileHeight) | |
137 { | |
138 } | |
279
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 |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
141 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
|
142 float& height) const |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
143 { |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
144 std::string s; |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
145 double mppx; |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
146 double mppy; |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
147 |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
148 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
|
149 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
|
150 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
|
151 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
|
152 { |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
153 // 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
|
154 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
|
155 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
|
156 return true; |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
157 } |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
158 else |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
159 { |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
160 return false; |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
161 } |
77afef2cf64b
automated extraction of the imaged volume if using OpenSlide
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
254
diff
changeset
|
162 } |
0 | 163 } |