Mercurial > hg > orthanc-wsi
comparison Framework/ImageToolbox.cpp @ 229:d9bd12e3747a
use Orthanc::ImageProcessing::Halve() instead of ImageToolbox::Halve()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 13 Jan 2021 17:40:56 +0100 |
parents | c6e7dda9ac14 |
children | c0a554576721 |
comparison
equal
deleted
inserted
replaced
228:c6e7dda9ac14 | 229:d9bd12e3747a |
---|---|
219 EncodeTile(target, *decoded, targetCompression, quality); | 219 EncodeTile(target, *decoded, targetCompression, quality); |
220 } | 220 } |
221 } | 221 } |
222 | 222 |
223 | 223 |
224 static uint8_t GetPixelValue(const Orthanc::ImageAccessor& source, | |
225 unsigned int x, | |
226 unsigned int y, | |
227 unsigned int channel, | |
228 int offsetX, | |
229 int offsetY, | |
230 unsigned int bytesPerPixel) | |
231 { | |
232 assert(bytesPerPixel == source.GetBytesPerPixel()); | |
233 assert(channel < bytesPerPixel); | |
234 assert(source.GetFormat() == Orthanc::PixelFormat_Grayscale8 || | |
235 source.GetFormat() == Orthanc::PixelFormat_RGB24 || | |
236 source.GetFormat() == Orthanc::PixelFormat_RGBA32); // 16bpp is unsupported | |
237 | |
238 if (static_cast<int>(x) + offsetX < 0) | |
239 { | |
240 x = 0; | |
241 } | |
242 else | |
243 { | |
244 x += offsetX; | |
245 if (x >= source.GetWidth()) | |
246 { | |
247 x = source.GetWidth() - 1; | |
248 } | |
249 } | |
250 | |
251 if (static_cast<int>(y) + offsetY < 0) | |
252 { | |
253 y = 0; | |
254 } | |
255 else | |
256 { | |
257 y += offsetY; | |
258 if (y >= source.GetHeight()) | |
259 { | |
260 y = source.GetHeight() - 1; | |
261 } | |
262 } | |
263 | |
264 return *(reinterpret_cast<const uint8_t*>(source.GetConstBuffer()) + | |
265 y * source.GetPitch() + x * bytesPerPixel + channel); | |
266 } | |
267 | |
268 | |
269 static uint8_t SmoothPixelValue(const Orthanc::ImageAccessor& source, | |
270 unsigned int x, | |
271 unsigned int y, | |
272 unsigned int channel, | |
273 unsigned int bytesPerPixel) | |
274 { | |
275 static const uint32_t kernel[5] = { 1, 4, 6, 4, 1 }; | |
276 static const uint32_t normalization = 2 * (1 + 4 + 6 + 4 + 1); | |
277 | |
278 uint32_t accumulator = 0; | |
279 | |
280 // Horizontal smoothing | |
281 for (int offset = -2; offset <= 2; offset++) | |
282 { | |
283 accumulator += kernel[offset + 2] * GetPixelValue(source, x, y, channel, offset, 0, bytesPerPixel); | |
284 } | |
285 | |
286 // Vertical smoothing | |
287 for (int offset = -2; offset <= 2; offset++) | |
288 { | |
289 accumulator += kernel[offset + 2] * GetPixelValue(source, x, y, channel, 0, offset, bytesPerPixel); | |
290 } | |
291 | |
292 return static_cast<uint8_t>(accumulator / normalization); | |
293 } | |
294 | |
295 | |
296 Orthanc::ImageAccessor* Halve(const Orthanc::ImageAccessor& source, | |
297 bool smooth) | |
298 { | |
299 if (source.GetWidth() % 2 == 1 || | |
300 source.GetHeight() % 2 == 1) | |
301 { | |
302 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); | |
303 } | |
304 | |
305 if (source.GetFormat() != Orthanc::PixelFormat_Grayscale8 && | |
306 source.GetFormat() != Orthanc::PixelFormat_RGB24 && | |
307 source.GetFormat() != Orthanc::PixelFormat_RGBA32) // 16bpp is not supported (*) | |
308 { | |
309 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
310 } | |
311 | |
312 const unsigned int bytesPerPixel = source.GetBytesPerPixel(); // Corresponds to the number of channels tx (*) | |
313 | |
314 std::unique_ptr<Orthanc::ImageAccessor> target(Allocate(source.GetFormat(), | |
315 source.GetWidth() / 2, | |
316 source.GetHeight() / 2)); | |
317 | |
318 const unsigned int width = target->GetWidth(); | |
319 const unsigned int height = target->GetHeight(); | |
320 | |
321 for (unsigned int y = 0; y < height; y++) | |
322 { | |
323 uint8_t* q = reinterpret_cast<uint8_t*>(target->GetRow(y)); | |
324 | |
325 for (unsigned int x = 0; x < width; x++, q += bytesPerPixel) | |
326 { | |
327 for (unsigned int c = 0; c < bytesPerPixel; c++) | |
328 { | |
329 if (smooth) | |
330 { | |
331 q[c] = SmoothPixelValue(source, 2 * x, 2 * y, c, bytesPerPixel); | |
332 } | |
333 else | |
334 { | |
335 q[c] = GetPixelValue(source, 2 * x, 2 * y, c, 0, 0, bytesPerPixel); | |
336 } | |
337 } | |
338 } | |
339 } | |
340 | |
341 return target.release(); | |
342 } | |
343 | |
344 | |
345 Orthanc::ImageAccessor* Render(ITiledPyramid& pyramid, | 224 Orthanc::ImageAccessor* Render(ITiledPyramid& pyramid, |
346 unsigned int level) | 225 unsigned int level) |
347 { | 226 { |
348 std::unique_ptr<Orthanc::ImageAccessor> result(Allocate(pyramid.GetPixelFormat(), | 227 std::unique_ptr<Orthanc::ImageAccessor> result(Allocate(pyramid.GetPixelFormat(), |
349 pyramid.GetLevelWidth(level), | 228 pyramid.GetLevelWidth(level), |