@@ -76,15 +76,88 @@ void ImagePyramidRenderer::loadAttributes() {
7676 setSharpening (getBooleanAttribute (" sharpening" ));
7777}
7878
79- void
80- ImagePyramidRenderer::draw (Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, float zNear, float zFar, bool mode2D,
81- int viewWidth,
82- int viewHeight) {
79+ int ImagePyramidRenderer::loadTileTexture (std::string tileID) {
80+ // Check if tile has been processed before
81+ if (mTexturesToRender .count (tileID) > 0 )
82+ return -1 ;
83+
84+ // std::cout << "Loading tile " << tileID << " queue size: " << m_tileQueue.size() << std::endl;
85+
86+ // Create texture
87+ auto parts = split (tileID, " _" );
88+ if (parts.size () != 3 )
89+ throw Exception (" incorrect tile format" );
90+
91+ int level = std::stoi (parts[0 ]);
92+ int tile_x = std::stoi (parts[1 ]);
93+ int tile_y = std::stoi (parts[2 ]);
94+ // std::cout << "Creating texture for tile " << tile_x << " " << tile_y << " at level " << level << std::endl;
95+ Image::pointer tile;
96+ {
97+ auto access = m_input->getAccess (ACCESS_READ);
98+ try {
99+ tile = access->getPatchAsImage (level, tile_x, tile_y, false );
100+ } catch (Exception &e) {
101+ // reportWarning() << "Error occured while trying to open patch " << tile_x << " " << tile_y << reportEnd();
102+ // Tile was missing, just skip it..
103+ std::lock_guard<std::mutex> lock (m_tileQueueMutex);
104+ mTexturesToRender [tileID] = 0 ;
105+ return -1 ;
106+ }
107+ if (m_postProcessingSharpening) {
108+ m_sharpening->setInputData (tile);
109+ tile = m_sharpening->updateAndGetOutputData <Image>();
110+ }
111+ }
112+ auto tileAccess = tile->getImageAccess (ACCESS_READ);
113+ // Copy data from CPU to GL texture
114+ GLuint textureID;
115+ glGenTextures (1 , &textureID);
116+ glBindTexture (GL_TEXTURE_2D, textureID);
117+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
118+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
119+
120+ // TODO Why is this needed:
121+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
122+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
123+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
124+
125+ // WSI data from openslide is stored as ARGB, need to handle this here: BGRA and reverse
126+ if (m_input->isBGRA ()) {
127+ glTexImage2D (GL_TEXTURE_2D, 0 , GL_COMPRESSED_RGBA, tile->getWidth (), tile->getHeight (), 0 , GL_BGRA,
128+ GL_UNSIGNED_BYTE,
129+ tileAccess->get ());
130+ } else {
131+ if (tile->getNrOfChannels () == 3 ) {
132+ glTexImage2D (GL_TEXTURE_2D, 0 , GL_COMPRESSED_RGB, tile->getWidth (), tile->getHeight (), 0 , GL_RGB,
133+ GL_UNSIGNED_BYTE,
134+ tileAccess->get ());
135+ } else if (tile->getNrOfChannels () == 4 ) {
136+ glTexImage2D (GL_TEXTURE_2D, 0 , GL_COMPRESSED_RGBA, tile->getWidth (), tile->getHeight (), 0 , GL_RGBA,
137+ GL_UNSIGNED_BYTE,
138+ tileAccess->get ());
139+ }
140+ }
141+ GLint compressedImageSize = 0 ;
142+ glGetTexLevelParameteriv (GL_TEXTURE_2D, 0 , GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressedImageSize);
143+ glBindTexture (GL_TEXTURE_2D, 0 );
144+ glFinish (); // Make sure texture is done before adding it
145+
146+ {
147+ std::lock_guard<std::mutex> lock (m_tileQueueMutex);
148+ mTexturesToRender [tileID] = textureID;
149+ }
150+ return compressedImageSize;
151+ }
152+
153+ void ImagePyramidRenderer::draw (Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, float zNear, float zFar, bool mode2D,
154+ int viewWidth,
155+ int viewHeight) {
83156 auto dataToRender = getDataToRender ();
84157 if (dataToRender.empty ())
85158 return ;
86159
87- if (!m_bufferThread) {
160+ if (!m_bufferThread && m_view != nullptr ) {
88161 // Create thread to load patches
89162 // Create a GL context for the thread which is sharing with the context of the view
90163 auto context = new QGLContext (View::getGLFormat (), m_view);
@@ -139,77 +212,7 @@ ImagePyramidRenderer::draw(Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, f
139212 m_tileQueue.pop_back ();
140213 }
141214
142- // Check if tile has been processed before
143- if (mTexturesToRender .count (tileID) > 0 )
144- continue ;
145-
146- // std::cout << "Loading tile " << tileID << " queue size: " << m_tileQueue.size() << std::endl;
147-
148- // Create texture
149- auto parts = split (tileID, " _" );
150- if (parts.size () != 3 )
151- throw Exception (" incorrect tile format" );
152-
153- int level = std::stoi (parts[0 ]);
154- int tile_x = std::stoi (parts[1 ]);
155- int tile_y = std::stoi (parts[2 ]);
156- // std::cout << "Creating texture for tile " << tile_x << " " << tile_y << " at level " << level << std::endl;
157- Image::pointer tile;
158- {
159- auto access = m_input->getAccess (ACCESS_READ);
160- try {
161- tile = access->getPatchAsImage (level, tile_x, tile_y, false );
162- } catch (Exception &e) {
163- // reportWarning() << "Error occured while trying to open patch " << tile_x << " " << tile_y << reportEnd();
164- // Tile was missing, just skip it..
165- std::lock_guard<std::mutex> lock (m_tileQueueMutex);
166- mTexturesToRender [tileID] = 0 ;
167- continue ;
168- }
169- if (m_postProcessingSharpening) {
170- m_sharpening->setInputData (tile);
171- tile = m_sharpening->updateAndGetOutputData <Image>();
172- }
173- }
174- auto tileAccess = tile->getImageAccess (ACCESS_READ);
175- // Copy data from CPU to GL texture
176- GLuint textureID;
177- glGenTextures (1 , &textureID);
178- glBindTexture (GL_TEXTURE_2D, textureID);
179- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
180- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
181-
182- // TODO Why is this needed:
183- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
184- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
185- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
186-
187- // WSI data from openslide is stored as ARGB, need to handle this here: BGRA and reverse
188- if (m_input->isBGRA ()) {
189- glTexImage2D (GL_TEXTURE_2D, 0 , GL_COMPRESSED_RGBA, tile->getWidth (), tile->getHeight (), 0 , GL_BGRA,
190- GL_UNSIGNED_BYTE,
191- tileAccess->get ());
192- } else {
193- if (tile->getNrOfChannels () == 3 ) {
194- glTexImage2D (GL_TEXTURE_2D, 0 , GL_COMPRESSED_RGB, tile->getWidth (), tile->getHeight (), 0 , GL_RGB,
195- GL_UNSIGNED_BYTE,
196- tileAccess->get ());
197- } else if (tile->getNrOfChannels () == 4 ) {
198- glTexImage2D (GL_TEXTURE_2D, 0 , GL_COMPRESSED_RGBA, tile->getWidth (), tile->getHeight (), 0 , GL_RGBA,
199- GL_UNSIGNED_BYTE,
200- tileAccess->get ());
201- }
202- }
203- GLint compressedImageSize = 0 ;
204- glGetTexLevelParameteriv (GL_TEXTURE_2D, 0 , GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressedImageSize);
205- glBindTexture (GL_TEXTURE_2D, 0 );
206- glFinish (); // Make sure texture is done before adding it
207-
208- {
209- std::lock_guard<std::mutex> lock (m_tileQueueMutex);
210- mTexturesToRender [tileID] = textureID;
211- }
212- memoryUsage += compressedImageSize;
215+ memoryUsage += loadTileTexture (tileID);
213216 // std::cout << "Texture cache in ImagePyramidRenderer using " << (float)memoryUsage / (1024 * 1024) << " MB" << std::endl;
214217 }
215218 });
@@ -251,7 +254,7 @@ ImagePyramidRenderer::draw(Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, f
251254 float percentageShownX = (float )width / fullWidth;
252255 float percentageShownY = (float )height / fullHeight;
253256 // With current level, do we have have enough pixels to fill the view?
254- if (percentageShownX * levelWidth > m_view-> width () && percentageShownY * levelHeight > m_view-> height () ) {
257+ if (percentageShownX * levelWidth > viewWidth && percentageShownY * levelHeight > viewHeight ) {
255258 // If yes, stop here
256259 levelToUse = level;
257260 break ;
@@ -337,26 +340,30 @@ ImagePyramidRenderer::draw(Matrix4f perspectiveMatrix, Matrix4f viewingMatrix, f
337340 ))
338341 continue ;
339342
340-
341- // Is patch in cache?
342- bool textureReady = false ;
343343 uint textureID;
344- {
345- std::lock_guard<std::mutex> lock (m_tileQueueMutex);
346- textureReady = mTexturesToRender .count (tileString) > 0 ;
347- }
348- if (!textureReady) {
349- // Add to queue if not in cache
344+ if (m_view != nullptr ) {
345+ // Is patch in cache?
346+ bool textureReady = false ;
350347 {
351348 std::lock_guard<std::mutex> lock (m_tileQueueMutex);
352- // Remove any duplicates first
353- m_tileQueue.remove (tileString); // O(n) time complexity..
354- m_tileQueue.push_back (tileString);
355- // std::cout << "Added tile " << tileString << " to queue" << std::endl;
349+ textureReady = mTexturesToRender .count (tileString) > 0 ;
350+ }
351+ if (!textureReady) {
352+ // Add to queue if not in cache
353+ {
354+ std::lock_guard<std::mutex> lock (m_tileQueueMutex);
355+ // Remove any duplicates first
356+ m_tileQueue.remove (tileString); // O(n) time complexity..
357+ m_tileQueue.push_back (tileString);
358+ // std::cout << "Added tile " << tileString << " to queue" << std::endl;
359+ }
360+ m_queueEmptyCondition.notify_one ();
361+ continue ;
362+ } else {
363+ textureID = mTexturesToRender [tileString];
356364 }
357- m_queueEmptyCondition.notify_one ();
358- continue ;
359365 } else {
366+ int bytes = loadTileTexture (tileString);
360367 textureID = mTexturesToRender [tileString];
361368 }
362369
0 commit comments