BioImager  4.9.0
A .NET microscopy imaging application based on Bio library. Supports various microscopes by using imported libraries & GUI automation. Supports XInput game controllers to move stage, take images, run ImageJ macros on images or Bio C# scripts.
Loading...
Searching...
No Matches
BioImager.SlideGLArea Class Reference
Inheritance diagram for BioImager.SlideGLArea:

Public Member Functions

bool UploadTileTexture (TileIndex index, byte[] pixelData, int tileWidth, int tileHeight)
 Upload a tile texture to the GPU. Call from the main thread. Returns true if upload succeeded.
 
bool HasTileTexture (TileIndex index)
 Check if a tile texture is already in the GPU cache.
 
void ReleaseTileTexture (TileIndex index)
 Release a specific tile texture.
 
void ReleaseLevelTextures (int level)
 Release all textures for a specific pyramid level.
 
void ClearTextureCache ()
 Clear all cached textures.
 
void RequestRedraw ()
 Request a redraw of the GLArea.
 
void SetOverlayBitmap (System.Drawing.Bitmap bitmap)
 
void ClearOverlayBitmap ()
 
void SetTilesToRender (IEnumerable< TileRenderInfo > tiles)
 Prepare tiles for rendering. Call before RequestRedraw().
 
byte[] ReadPixels ()
 Read pixels from the current framebuffer (for export/save operations). This is slow — only use for export, not display.
 

Properties

List< TileRenderInfoTilesToRender = new() [get]
 
bool NeedsRedraw [get]
 
bool IsGLReady [get]
 True after the GL context has been fully initialized and is ready for texture uploads and rendering.
 
int CachedTextureCount [get]
 

Events

EventHandler GLReady
 Fires exactly once after the GL context has been successfully initialized. Subscribe to this from ImageView to trigger the first tile load at a point where GL texture uploads are guaranteed to work.
 

Detailed Description

Definition at line 14 of file SlideGLArea.cs.

Constructor & Destructor Documentation

◆ SlideGLArea()

BioImager.SlideGLArea.SlideGLArea ( )

Definition at line 120 of file SlideGLArea.cs.

121 {
122 Paint += OnPaint;
123 Disposed += OnDisposed;
124 Resize += OnResized;
125 }

Member Function Documentation

◆ ClearOverlayBitmap()

void BioImager.SlideGLArea.ClearOverlayBitmap ( )

Definition at line 696 of file SlideGLArea.cs.

697 {
698 _overlayPixels = null;
699 _overlayWidth = 0;
700 _overlayHeight = 0;
701 _overlayDirty = true;
703 }
void RequestRedraw()
Request a redraw of the GLArea.

◆ ClearTextureCache()

void BioImager.SlideGLArea.ClearTextureCache ( )

Clear all cached textures.

Definition at line 618 of file SlideGLArea.cs.

619 {
620 if (!_glInitialized) return;
621
622 MakeCurrent();
623
624 foreach (var tex in _textureCache.Values)
625 GL.DeleteTexture(tex);
626
627 _textureCache.Clear();
628 }

◆ HasTileTexture()

bool BioImager.SlideGLArea.HasTileTexture ( TileIndex index)

Check if a tile texture is already in the GPU cache.

Definition at line 580 of file SlideGLArea.cs.

581 {
582 return _textureCache.ContainsKey(index);
583 }

◆ ReadPixels()

byte[] BioImager.SlideGLArea.ReadPixels ( )

Read pixels from the current framebuffer (for export/save operations). This is slow — only use for export, not display.

Definition at line 720 of file SlideGLArea.cs.

721 {
722 if (!_glInitialized) return null;
723
724 MakeCurrent();
725
726 int width = Width;
727 int height = Height;
728
729 byte[] pixels = new byte[width * height * 4];
730 GL.ReadPixels(0, 0, width, height, PixelFormat.Rgba, PixelType.UnsignedByte, pixels);
731
732 return pixels;
733 }

◆ ReleaseLevelTextures()

void BioImager.SlideGLArea.ReleaseLevelTextures ( int level)

Release all textures for a specific pyramid level.

Definition at line 601 of file SlideGLArea.cs.

602 {
603 if (!_glInitialized) return;
604
605 MakeCurrent();
606
607 var toRemove = _textureCache.Where(kvp => kvp.Key.Level == level).ToList();
608 foreach (var kvp in toRemove)
609 {
610 GL.DeleteTexture(kvp.Value);
611 _textureCache.Remove(kvp.Key);
612 }
613 }

◆ ReleaseTileTexture()

void BioImager.SlideGLArea.ReleaseTileTexture ( TileIndex index)

Release a specific tile texture.

Definition at line 588 of file SlideGLArea.cs.

589 {
590 if (_textureCache.TryGetValue(index, out int tex))
591 {
592 MakeCurrent();
593 GL.DeleteTexture(tex);
594 _textureCache.Remove(index);
595 }
596 }

◆ RequestRedraw()

void BioImager.SlideGLArea.RequestRedraw ( )

Request a redraw of the GLArea.

Definition at line 648 of file SlideGLArea.cs.

649 {
650 NeedsRedraw = true;
651 Invalidate();
652 }

◆ SetOverlayBitmap()

void BioImager.SlideGLArea.SetOverlayBitmap ( System.Drawing.Bitmap bitmap)

Definition at line 654 of file SlideGLArea.cs.

655 {
656 if (bitmap == null)
657 {
658 _overlayPixels = null;
659 _overlayWidth = 0;
660 _overlayHeight = 0;
661 _overlayDirty = true;
663 return;
664 }
665
666 var rect = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height);
667 var data = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
668
669 try
670 {
671 int rowBytes = bitmap.Width * 4;
672 byte[] buffer = new byte[rowBytes * bitmap.Height];
673 int stride = data.Stride;
674 int absStride = Math.Abs(stride);
675
676 for (int y = 0; y < bitmap.Height; y++)
677 {
678 IntPtr srcRow = stride >= 0
679 ? IntPtr.Add(data.Scan0, y * stride)
680 : IntPtr.Add(data.Scan0, (bitmap.Height - 1 - y) * absStride);
681 Marshal.Copy(srcRow, buffer, y * rowBytes, rowBytes);
682 }
683
684 _overlayPixels = buffer;
685 _overlayWidth = bitmap.Width;
686 _overlayHeight = bitmap.Height;
687 _overlayDirty = true;
689 }
690 finally
691 {
692 bitmap.UnlockBits(data);
693 }
694 }

◆ SetTilesToRender()

void BioImager.SlideGLArea.SetTilesToRender ( IEnumerable< TileRenderInfo > tiles)

Prepare tiles for rendering. Call before RequestRedraw().

Definition at line 708 of file SlideGLArea.cs.

709 {
710 TilesToRender.Clear();
711 TilesToRender.AddRange(tiles);
712 }

◆ UploadTileTexture()

bool BioImager.SlideGLArea.UploadTileTexture ( TileIndex index,
byte[] pixelData,
int tileWidth,
int tileHeight )

Upload a tile texture to the GPU. Call from the main thread. Returns true if upload succeeded.

Definition at line 418 of file SlideGLArea.cs.

419 {
420 if (pixelData == null || pixelData.Length == 0)
421 return false;
422
423 // Guard: don't attempt GL operations if the context isn't ready
424 if (!IsHandleCreated)
425 {
426 return false;
427 }
428
429 try
430 {
431 MakeCurrent();
432 }
433 catch
434 {
435 return false;
436 }
437
438 if (!_glInitialized)
439 InitializeGL();
440
441 if (!_glInitialized)
442 {
443 return false;
444 }
445
446 // Already cached — nothing to do
447 if (_textureCache.ContainsKey(index))
448 return true;
449
450 // Evict old textures if cache is full
451 if (_textureCache.Count >= MAX_CACHED_TEXTURES)
452 EvictOldestTextures(MAX_CACHED_TEXTURES / 4);
453
454 int expectedPixels = tileWidth * tileHeight;
455 if (expectedPixels <= 0)
456 return false;
457
458 byte[] uploadData = pixelData;
459 PixelFormat uploadFormat = PixelFormat.Bgra;
460 int expectedBytes = expectedPixels * 4;
461
462 if (pixelData.Length == expectedBytes)
463 {
464 // Already BGRA.
465 }
466 else if (pixelData.Length == expectedPixels * 3)
467 {
468 uploadData = Convert24BitRgbToBgra(pixelData, expectedPixels);
469 }
470 else if (pixelData.Length >= expectedPixels * 2)
471 {
472 uploadData = Convert16BitGrayToBgra(pixelData, expectedPixels);
473 }
474 else if (pixelData.Length >= expectedPixels)
475 {
476 uploadData = Convert8BitGrayToBgra(pixelData, expectedPixels);
477 }
478 else
479 {
480 return false;
481 }
482
483 // Create and upload texture
484 int tex = GL.GenTexture();
485 GL.BindTexture(TextureTarget.Texture2D, tex);
486 GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
487
488 // OpenSlide-style tile buffers arrive as BGRA on little-endian systems.
489 // Using the matching OpenGL pixel format avoids channel/alpha mismatches.
490 GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
491 tileWidth, tileHeight, 0, uploadFormat, PixelType.UnsignedByte, uploadData);
492
493 var glErr = GL.GetError();
494 if (glErr != ErrorCode.NoError)
495 {
496 GL.DeleteTexture(tex);
497 return false;
498 }
499
500 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
501 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
502 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
503 GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
504
505 GL.BindTexture(TextureTarget.Texture2D, 0);
506 _textureCache[index] = tex;
507 return true;
508 }

Property Documentation

◆ CachedTextureCount

int BioImager.SlideGLArea.CachedTextureCount
get

Definition at line 714 of file SlideGLArea.cs.

◆ IsGLReady

bool BioImager.SlideGLArea.IsGLReady
get

True after the GL context has been fully initialized and is ready for texture uploads and rendering.

Definition at line 67 of file SlideGLArea.cs.

◆ NeedsRedraw

bool BioImager.SlideGLArea.NeedsRedraw
get

Definition at line 49 of file SlideGLArea.cs.

49{ get; private set; }

◆ TilesToRender

List<TileRenderInfo> BioImager.SlideGLArea.TilesToRender = new()
get

Definition at line 48 of file SlideGLArea.cs.

48{ get; } = new();

Event Documentation

◆ GLReady

EventHandler BioImager.SlideGLArea.GLReady

Fires exactly once after the GL context has been successfully initialized. Subscribe to this from ImageView to trigger the first tile load at a point where GL texture uploads are guaranteed to work.

Definition at line 60 of file SlideGLArea.cs.


The documentation for this class was generated from the following file: