Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save petebankhead/98d82f5de92abefaf4cfd87ec0479121 to your computer and use it in GitHub Desktop.

Select an option

Save petebankhead/98d82f5de92abefaf4cfd87ec0479121 to your computer and use it in GitHub Desktop.
Proof-of-concept script showing one whole slide image as an overlay on top of another within QuPath.
/**
* Proof-of-concept script showing one whole slide image as an overlay on top
* of another within QuPath.
*
* Note that this script simply overlays the *same* image that is currently open;
* therefore it may not be immediately obvious that anything has happened.
*
* Uncomment the line
* g2d.translate(1000, 1000)
* if you want to convince yourself that something *has* actually happened,
* and adjust the opacity slider as required.
*
* In practice, it will be more useful to overlay a *different* image...
*
* Note that you can also optionally bind the overlay display to the show/hide detections option.
*
* WARNING! This should work in QuPath v0.1.2, and possibly v0.1.3.
* However, the API will definitely change in the future as overlays become
* a more important part of the software... therefore be prepared to update any
* code based on this.
*
* @author Pete Bankhead
*/
import javafx.application.Platform
import qupath.lib.awt.common.AwtTools
import qupath.lib.gui.viewer.QuPathViewer
import qupath.lib.gui.viewer.overlays.AbstractImageDataOverlay
import qupath.lib.images.ImageData
import qupath.lib.images.servers.ImageServer
import qupath.lib.images.servers.ImageServerProvider
import qupath.lib.regions.ImageRegion
import qupath.lib.scripting.QPEx
import java.awt.Graphics2D
import java.awt.Shape
import java.awt.geom.AffineTransform
import java.awt.image.BufferedImage
import java.awt.image.ImageObserver
// Replace overlay in the Application thread
Platform.runLater {
def viewer = QPEx.getCurrentViewer()
def path = viewer.getServerPath()
def overlay = new WholeSlideImageOverlay(viewer, path, false)
// Remove any existing overlays of this kind (helpful during debugging...)
viewer.getOverlayLayers().findAll({it.getClass().getName().contains('WholeSlideImageOverlay')}).each {
viewer.removeOverlay(it)
}
// Add the new overlay
viewer.addOverlay(overlay)
print 'Done!'
}
/**
* Create an overlay to display one whole slide image on top of another.
*/
class WholeSlideImageOverlay extends AbstractImageDataOverlay {
private boolean initialized = false
private QuPathViewer viewer
private ImageServer<BufferedImage> server
private AffineTransform transform
private boolean bindToObjectDisplay
public WholeSlideImageOverlay(final QuPathViewer viewer, final String path, boolean bindToObjectDisplay) {
super(viewer.getOverlayOptions(), viewer.getImageData())
this.viewer = viewer
this.server = ImageServerProvider.buildServer(path, BufferedImage.class)
this.initialized = true
this.bindToObjectDisplay = bindToObjectDisplay
}
@Override
boolean supportsImageDataChange() {
return true
}
/**
* If the ImageData for the viewer is changed, remove the overlay.
*
* @param imageData
*/
@Override
public void setImageData(final ImageData<BufferedImage> imageData) {
if (this.imageData == imageData || !initialized)
return
viewer.removeOverlay(this)
this.server.close()
}
@Override
void paintOverlay(Graphics2D g2d, ImageRegion imageRegion, double downsampleFactor, ImageObserver observer, boolean paintCompletely) {
// Don't do anything if opacity is zero
if (getOpacity() == 0)
return
// If we're binding this to the display of objects, don't paint if detections aren't visible
// (this lets us toggle the overlay on & off with the 'h' shortcut)
if (bindToObjectDisplay && !viewer.getOverlayOptions().showObjects)
return
// Create a rectangle for the region
Shape shape = AwtTools.getBounds(imageRegion)
// Apply transform... handy if using the same image, just to check *something* happens
// g2d.translate(1000, 1000)
// Paint region with the help of the image region store (used for caching & painting)
int z = viewer.getZPosition()
int t = viewer.getTPosition()
viewer.getImageRegionStore().paintRegion(
server, g2d, g2d.getClip(), z, t, downsampleFactor,
viewer.getImageRegionStore().getThumbnail(server, z, t, true),
null, null)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment