comparison Framework/Algorithms/ReconstructPyramidCommand.cpp @ 0:4a7a53257c7d

initial commit
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sat, 22 Oct 2016 21:48:33 +0200
parents
children 7a88c614be04
comparison
equal deleted inserted replaced
-1:000000000000 0:4a7a53257c7d
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 *
6 * This program is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU Affero General Public License
8 * as published by the Free Software Foundation, either version 3 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 **/
19
20
21 #include "ReconstructPyramidCommand.h"
22
23 #include "../ImageToolbox.h"
24 #include "../Orthanc/Core/Logging.h"
25 #include "../Orthanc/Core/OrthancException.h"
26 #include "../Orthanc/Core/Images/Image.h"
27
28 #include <cassert>
29
30 namespace OrthancWSI
31 {
32 Orthanc::ImageAccessor* ReconstructPyramidCommand::Explore(unsigned int level,
33 unsigned int offsetX,
34 unsigned int offsetY)
35 {
36 unsigned int zoom = 1 << level;
37 assert(x_ % zoom == 0 && y_ % zoom == 0);
38 unsigned int x = x_ / zoom + offsetX;
39 unsigned int y = y_ / zoom + offsetY;
40
41 if (x >= target_.GetCountTilesX(level + shiftTargetLevel_) ||
42 y >= target_.GetCountTilesY(level + shiftTargetLevel_))
43 {
44 return NULL;
45 }
46
47 std::auto_ptr<Orthanc::ImageAccessor> result;
48
49 if (level == 0)
50 {
51 result.reset(new Orthanc::ImageAccessor(source_.GetDecodedTile(x, y)));
52
53 const std::string* rawTile = source_.GetRawTile(x, y);
54
55 if (rawTile != NULL)
56 {
57 // Simple transcoding
58 target_.WriteRawTile(*rawTile, source_.GetImageCompression(), level + shiftTargetLevel_, x, y);
59 }
60 else
61 {
62 // Re-encoding the file
63 target_.EncodeTile(*result, level + shiftTargetLevel_, x, y);
64 }
65 }
66 else
67 {
68 std::auto_ptr<Orthanc::ImageAccessor> mosaic(ImageToolbox::Allocate(source_.GetPixelFormat(),
69 2 * target_.GetTileWidth(),
70 2 * target_.GetTileHeight()));
71 ImageToolbox::Set(*mosaic,
72 source_.GetParameters().GetBackgroundColorRed(),
73 source_.GetParameters().GetBackgroundColorGreen(),
74 source_.GetParameters().GetBackgroundColorBlue());
75
76 {
77 std::auto_ptr<Orthanc::ImageAccessor> subTile(Explore(level - 1, 2 * offsetX, 2 * offsetY));
78 if (subTile.get() != NULL)
79 {
80 ImageToolbox::Embed(*mosaic, *subTile, 0, 0);
81 }
82 }
83
84 {
85 std::auto_ptr<Orthanc::ImageAccessor> subTile(Explore(level - 1, 2 * offsetX + 1, 2 * offsetY));
86 if (subTile.get() != NULL)
87 {
88 ImageToolbox::Embed(*mosaic, *subTile, target_.GetTileWidth(), 0);
89 }
90 }
91
92 {
93 std::auto_ptr<Orthanc::ImageAccessor> subTile(Explore(level - 1, 2 * offsetX, 2 * offsetY + 1));
94 if (subTile.get() != NULL)
95 {
96 ImageToolbox::Embed(*mosaic, *subTile, 0, target_.GetTileHeight());
97 }
98 }
99
100 {
101 std::auto_ptr<Orthanc::ImageAccessor> subTile(Explore(level - 1, 2 * offsetX + 1, 2 * offsetY + 1));
102 if (subTile.get() != NULL)
103 {
104 ImageToolbox::Embed(*mosaic, *subTile, target_.GetTileWidth(), target_.GetTileHeight());
105 }
106 }
107
108 result.reset(ImageToolbox::Halve(*mosaic, source_.GetParameters().IsSmoothEnabled()));
109
110 target_.EncodeTile(*result, level + shiftTargetLevel_, x, y);
111 }
112
113 return result.release();
114 }
115
116
117 ReconstructPyramidCommand::ReconstructPyramidCommand(IPyramidWriter& target,
118 ITiledPyramid& source,
119 unsigned int upToLevel,
120 unsigned int x,
121 unsigned int y,
122 const DicomizerParameters& parameters) :
123 target_(target),
124 source_(source, 0, target.GetTileWidth(), target.GetTileHeight(), parameters),
125 upToLevel_(upToLevel),
126 x_(x),
127 y_(y),
128 shiftTargetLevel_(0)
129 {
130 unsigned int zoom = 1 << upToLevel;
131 if (x % zoom != 0 ||
132 y % zoom != 0)
133 {
134 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
135 }
136
137 if (target.GetPixelFormat() != source.GetPixelFormat())
138 {
139 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageFormat);
140 }
141 }
142
143
144 bool ReconstructPyramidCommand::Execute()
145 {
146 std::auto_ptr<Orthanc::ImageAccessor> root(Explore(upToLevel_, 0, 0));
147 return true;
148 }
149
150
151 void ReconstructPyramidCommand::PrepareBagOfTasks(Orthanc::BagOfTasks& tasks,
152 IPyramidWriter& target,
153 ITiledPyramid& source,
154 unsigned int countLevels,
155 unsigned int shiftTargetLevel,
156 const DicomizerParameters& parameters)
157 {
158 if (countLevels == 0)
159 {
160 return;
161 }
162
163 if (shiftTargetLevel + countLevels > target.GetLevelCount())
164 {
165 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
166 }
167
168 const unsigned int targetCountTilesX = target.GetCountTilesX(shiftTargetLevel);
169 const unsigned int targetCountTilesY = target.GetCountTilesY(shiftTargetLevel);
170 const unsigned int step = 1 << (countLevels - 1);
171
172 for (unsigned int y = 0; y < targetCountTilesY; y += step)
173 {
174 for (unsigned int x = 0; x < targetCountTilesX; x += step)
175 {
176 std::auto_ptr<ReconstructPyramidCommand> command;
177 command.reset(new ReconstructPyramidCommand
178 (target, source, countLevels - 1, x, y, parameters));
179 command->SetShiftTargetLevel(shiftTargetLevel);
180 tasks.Push(command.release());
181 }
182 }
183 }
184 }