comparison Framework/Inputs/OpenSlidePyramid.cpp @ 315:072968f00d26

support of transparency in OpenSlide
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 09 Sep 2024 20:12:14 +0200
parents 0683312e21ba
children f611fb47d0e8
comparison
equal deleted inserted replaced
314:9dc7f1e8716d 315:072968f00d26
28 #include <Images/ImageProcessing.h> 28 #include <Images/ImageProcessing.h>
29 #include <OrthancException.h> 29 #include <OrthancException.h>
30 #include <SerializationToolbox.h> 30 #include <SerializationToolbox.h>
31 #include <Logging.h> 31 #include <Logging.h>
32 32
33 #include <boost/math/special_functions/round.hpp>
33 #include <memory> 34 #include <memory>
34 35
35 namespace OrthancWSI 36 namespace OrthancWSI
36 { 37 {
37 void OpenSlidePyramid::ReadRegion(Orthanc::ImageAccessor& target, 38 void OpenSlidePyramid::ReadRegion(Orthanc::ImageAccessor& target,
38 unsigned int level, 39 unsigned int level,
39 unsigned int x, 40 unsigned int x,
40 unsigned int y) 41 unsigned int y)
41 { 42 {
42 std::unique_ptr<Orthanc::ImageAccessor> source(image_.ReadRegion(level, x, y, target.GetWidth(), target.GetHeight())); 43 std::unique_ptr<Orthanc::ImageAccessor> source(image_.ReadRegion(level, x, y, target.GetWidth(), target.GetHeight()));
43 Orthanc::ImageProcessing::Convert(target, *source); 44
45 if (target.GetWidth() != source->GetWidth() ||
46 target.GetHeight() != source->GetHeight())
47 {
48 throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize);
49 }
50
51 const unsigned int width = source->GetWidth();
52 const unsigned int height = source->GetHeight();
53
54 if (target.GetFormat() == Orthanc::PixelFormat_RGB24 &&
55 source->GetFormat() == Orthanc::PixelFormat_BGRA32)
56 {
57 // Implements alpha blending: https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
58 for (unsigned int y = 0; y < height; y++)
59 {
60 const uint8_t* p = reinterpret_cast<const uint8_t*>(source->GetConstRow(y));
61 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y));
62 for (unsigned int x = 0; x < width; x++)
63 {
64 /**
65 Alpha blending using integer arithmetics only (16 bits avoids overflows)
66
67 p = (1 - alpha) * background + alpha * value
68 <=> p = (1 - p[3] / 255) * background + p[3] / 255 * value
69 <=> p = ((255 - p[3]) * background + p[3] * value) / 255
70
71 **/
72
73 uint16_t alpha = p[3];
74 q[0] = static_cast<uint8_t>(((255 - alpha) * backgroundColor_[0] + alpha * p[2]) / 255);
75 q[1] = static_cast<uint8_t>(((255 - alpha) * backgroundColor_[1] + alpha * p[1]) / 255);
76 q[2] = static_cast<uint8_t>(((255 - alpha) * backgroundColor_[2] + alpha * p[0]) / 255);
77
78 p += 4;
79 q += 3;
80 }
81 }
82 }
83 else
84 {
85 Orthanc::ImageProcessing::Convert(target, *source);
86 }
44 } 87 }
45 88
46 89
47 OpenSlidePyramid::OpenSlidePyramid(const std::string& path, 90 OpenSlidePyramid::OpenSlidePyramid(const std::string& path,
48 unsigned int tileWidth, 91 unsigned int tileWidth,
49 unsigned int tileHeight) : 92 unsigned int tileHeight) :
50 image_(path), 93 image_(path),
51 tileWidth_(tileWidth), 94 tileWidth_(tileWidth),
52 tileHeight_(tileHeight) 95 tileHeight_(tileHeight)
53 { 96 {
97 backgroundColor_[0] = 255;
98 backgroundColor_[1] = 255;
99 backgroundColor_[2] = 255;
54 } 100 }
55 101
56 102
57 bool OpenSlidePyramid::LookupImagedVolumeSize(float& width, 103 bool OpenSlidePyramid::LookupImagedVolumeSize(float& width,
58 float& height) const 104 float& height) const
74 else 120 else
75 { 121 {
76 return false; 122 return false;
77 } 123 }
78 } 124 }
125
126
127 void OpenSlidePyramid::SetBackgroundColor(uint8_t red,
128 uint8_t green,
129 uint8_t blue)
130 {
131 backgroundColor_[0] = red;
132 backgroundColor_[1] = green;
133 backgroundColor_[2] = blue;
134 }
79 } 135 }