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),