Exporting single-composite images

Hi everyone.

I’m looking for a way to export images displaying one channel at a time for a whole project. I’ve been using this script that I got off one of Pete’s old posts so far for exporting images however it doesn’t seem to take the current brightness and contrast settings into account.

If anyone has a script or some suggestions that would be great! Ideally I’d like to use a scripted version of the File > Export snapshot > Current Viewer Content.

/**
 * Export a thumbnail image, with and without an overlay, using QuPath.
 *
 * For tissue microarrays, the scripting code written by the 'File -> Export TMA data'
 * command is probably more appropriate.
 *
 * However, for all other kinds of images where batch export is needed this script can be used.
 *
 * @author Pete Bankhead
 */


import qupath.lib.gui.ImageWriterTools
import qupath.lib.gui.QuPathGUI
import qupath.lib.gui.viewer.OverlayOptions
import qupath.lib.regions.RegionRequest

// Aim for an output resolution of approx 20 µm/pixel
double requestedPixelSize = 1

// Create the output directory, if required
def path = buildFilePath(PROJECT_BASE_DIR, "image_exports")
mkdirs(path)

// Get the imageData & server
def imageData = getCurrentImageData()
def server = imageData.getServer()

// Get the file name from the current server
def name = server.getShortServerName()

// We need to get the display settings (colors, line thicknesses, opacity etc.) from the current viewer, if available
def overlayOptions = QuPathGUI.getInstance() == null ? new OverlayOptions() : QuPathGUI.getInstance().getViewer().getOverlayOptions()

// Calculate downsample factor depending on the requested pixel size
double downsample = requestedPixelSize / server.getAveragedPixelSizeMicrons()
def request = RegionRequest.createInstance(imageData.getServerPath(), downsample, 0, 0, server.getWidth(), server.getHeight())

// Write output image, with and without overlay
def dir = new File(path)
def fileImage = new File(dir, name + ".tif")
def img = ImageWriterTools.writeImageRegion(server, request, fileImage.getAbsolutePath())
def fileImageWithOverlay = new File(dir, name + ".tif")
ImageWriterTools.writeImageRegionWithOverlay(img, imageData, overlayOptions, request, fileImageWithOverlay.getAbsolutePath())

I’ve recently rewritten how QuPath can write out image regions, so in QuPath v0.2.0-m5 this should be considerably easier. I hope this will be available next week but I’ve been wrong before…

I’m not sure what version you’re using, but in the meantime this adaption may get it working work in v0.2.0-m4:

import qupath.lib.gui.ImageWriterTools
import qupath.lib.gui.QuPathGUI
import qupath.lib.gui.viewer.OverlayOptions
import qupath.lib.regions.RegionRequest

// Aim for an output resolution of approx 20 µm/pixel
double requestedPixelSize = 1

// Create the output directory, if required
def path = buildFilePath(PROJECT_BASE_DIR, "image_exports")
mkdirs(path)

// Get the imageData & server
def imageData = getCurrentImageData()
def server = imageData.getServer()

// Get the file name from the current server
def name = server.getMetadata().getName()

// We need to get the display settings (colors, line thicknesses, opacity etc.) from the current viewer, if available
def overlayOptions = QuPathGUI.getInstance() == null ? new OverlayOptions() : QuPathGUI.getInstance().getViewer().getOverlayOptions()

// Calculate downsample factor depending on the requested pixel size
double downsample = requestedPixelSize / server.getPixelCalibration().getAveragedPixelSizeMicrons()
def request = RegionRequest.createInstance(imageData.getServerPath(), downsample, 0, 0, server.getWidth(), server.getHeight())

// Write output image, with and without overlay
def dir = new File(path)
def imgOrig = server.readBufferedImage(request)
def img = getCurrentViewer().getImageDisplay().applyTransforms(imgOrig, null)
def fileImageWithOverlay = new File(dir, name + ".tif")
ImageWriterTools.writeImageRegionWithOverlay(img, imageData, overlayOptions, request, fileImageWithOverlay.getAbsolutePath())

If so it’s only temporary though… also, it will use the brightness/contrast settings for the current image open in the viewer - it won’t (I think…) apply them separately for each image in the project.

2 Likes

This is exactly what I needed. Thank you Pete!

2 Likes