Problem of convertToUncalibratedImagePlus when dataType == DataBuffer.TYPE_BYTE && (sampleModel.getNumBands() == 1

I open a simple 8-bit single channel tif in QuPath and try to get imp and show it:
PyramidalCell-ome_Z001.tif (67.3 KB) PyramidalCell-series-_Z001.tif (66.7 KB)

	img = server.readBufferedImage(request);
	imp = IJTools.convertToUncalibratedImagePlus(title,img);
	imp.show();

I have checked that the sampleModel.getNumBands() == 1:

	aSampleModel = img.getSampleModel();
	aNumBands = aSampleModel.getNumBands();

thus the code should go to the bottom one:

	// Create whatever image ImageJ will give us (worked for color or 8-bit gray)
	imp = new ImagePlus(title, img);

However,
For the two tif files they shows difference:
For PyramidalCell-ome_Z001.tif, which is exported as ome tiff, imp shows 8-bit normal image on screen, and QuPath print log:

11:17:00.119 [main] [INFO ] loci.formats.in.MinimalTiffReader - Reading IFDs 
			11:17:00.129 [main] [INFO ] loci.formats.in.MinimalTiffReader - Populating metadata 
			11:17:00.129 [main] [INFO ] loci.formats.in.TiffReader - Checking comment style 
			11:17:00.139 [main] [INFO ] loci.formats.in.BaseTiffReader - Populating OME metadata 
			11:17:00.209 [main] [INFO ] loci.formats.in.MinimalTiffReader - Reading IFDs 
			11:17:00.219 [main] [INFO ] loci.formats.in.MinimalTiffReader - Populating metadata 
			11:17:00.219 [main] [INFO ] loci.formats.in.TiffReader - Checking comment style 
			11:17:00.219 [main] [INFO ] loci.formats.in.BaseTiffReader - Populating OME metadata

but for PyramidalCell-series-_Z001.tif which is exported as adjustable tiff series, it shows black RGB image with no image content, and no log is printed out.

These two images opens with no problem in QuPath, but the results is so different:
I cannot find a way to get a corrrect imp from PyramidalCell-series-_Z001.tif,even if I use
imp = IJTools.convertToImagePlus(server__,request).getImage();

public static ImagePlus convertToUncalibratedImagePlus(String title, BufferedImage img) {
			ImagePlus imp = null;
			SampleModel sampleModel = img.getSampleModel();
			int dataType = sampleModel.getDataType();
			int w = img.getWidth();
			int h = img.getHeight();
			if ((dataType == DataBuffer.TYPE_BYTE && (sampleModel.getNumBands() != 1 || img.getType() == BufferedImage.TYPE_BYTE_INDEXED)) ||
					dataType == DataBuffer.TYPE_USHORT || dataType == DataBuffer.TYPE_SHORT || dataType == DataBuffer.TYPE_FLOAT || dataType == DataBuffer.TYPE_DOUBLE) {
				// Handle non-8-bit images
				ImageStack stack = new ImageStack(w, h);
				for (int b = 0; b < sampleModel.getNumBands(); b++) {
					// Read data as float (no matter what it is)
					FloatProcessor fp = new FloatProcessor(w, h);
					float[] pixels = (float[])fp.getPixels();
					img.getRaster().getSamples(0, 0, w, h, b, pixels);
	//				sampleModel.getSamples(0, 0, w, h, b, pixels, img.getRaster().getDataBuffer());
					// Convert to 8 or 16-bit, if appropriate
					if (dataType == DataBuffer.TYPE_BYTE) {
						ByteProcessor bp = new ByteProcessor(w, h);
						bp.setPixels(0, fp);
						stack.addSlice(bp);
					} else if (dataType == DataBuffer.TYPE_USHORT) {
						ShortProcessor sp = new ShortProcessor(w, h);
						sp.setPixels(0, fp);
						stack.addSlice(sp);
					} else
						stack.addSlice(fp);
				}
				imp = new ImagePlus(title, stack);
			} else {
				// Create whatever image ImageJ will give us (worked for color or 8-bit gray)
				imp = new ImagePlus(title, img);
			}
			return imp;
		}

The only difference between the image information of the two tif is :“ImageDescription”


>> imfinfo('D:\QMDownload\9\PyramidalCell-series-_Z001.tif')

ans = 

                     Filename: 'D:\QMDownload\9\PyramidalCell-series-_Z001.tif'
                  FileModDate: '04-12月-2020 01:27:31'
                     FileSize: 68306
                       Format: 'tif'
                FormatVersion: []
                        Width: 255
                       Height: 255
                     BitDepth: 8
                    ColorType: 'grayscale'
              FormatSignature: [73 73 42 0]
                    ByteOrder: 'little-endian'
               NewSubFileType: 0
                BitsPerSample: 8
                  Compression: 'Uncompressed'
    PhotometricInterpretation: 'BlackIsZero'
                 StripOffsets: [1x255 double]
              SamplesPerPixel: 1
                 RowsPerStrip: 1
              StripByteCounts: [1x255 double]
                  XResolution: 4.4000e+04
                  YResolution: 4.3828e+04
               ResolutionUnit: 'Centimeter'
                     Colormap: []
          PlanarConfiguration: 'Chunky'
                    TileWidth: []
                   TileLength: []
                  TileOffsets: []
               TileByteCounts: []
                  Orientation: 1
                    FillOrder: 1
             GrayResponseUnit: 0.0100
               MaxSampleValue: 255
               MinSampleValue: 0
                 Thresholding: 1
                       Offset: 65034
             ImageDescription: '[ImarisDataSet]…'
                 SampleFormat: 'Unsigned integer'
				 
				 
 >> imfinfo('D:\QMDownload\9\PyramidalCell-ome_Z001.tif')

ans = 

                     Filename: 'D:\QMDownload\9\PyramidalCell-ome_Z001.tif'
                  FileModDate: '04-12月-2020 01:27:52'
                     FileSize: 68954
                       Format: 'tif'
                FormatVersion: []
                        Width: 255
                       Height: 255
                     BitDepth: 8
                    ColorType: 'grayscale'
              FormatSignature: [73 73 42 0]
                    ByteOrder: 'little-endian'
               NewSubFileType: 0
                BitsPerSample: 8
                  Compression: 'Uncompressed'
    PhotometricInterpretation: 'BlackIsZero'
                 StripOffsets: [1x255 double]
              SamplesPerPixel: 1
                 RowsPerStrip: 1
              StripByteCounts: [1x255 double]
                  XResolution: 4.4000e+04
                  YResolution: 4.3828e+04
               ResolutionUnit: 'Centimeter'
                     Colormap: []
          PlanarConfiguration: 'Chunky'
                    TileWidth: []
                   TileLength: []
                  TileOffsets: []
               TileByteCounts: []
                  Orientation: 1
                    FillOrder: 1
             GrayResponseUnit: 0.0100
               MaxSampleValue: 255
               MinSampleValue: 0
                 Thresholding: 1
                       Offset: 65034
             ImageDescription: '<?xml version = "1.0" encoding = "UTF-8"?>…'
                 SampleFormat: 'Unsigned integer'

I don’t understand the problem. A complete version of the first script you posted works for me

def server = getCurrentServer()
def request = RegionRequest.createInstance(server)
img = server.readBufferedImage(request);
imp = IJTools.convertToUncalibratedImagePlus("Anything else",img);
imp.show();

Similarly, this works – and is preferable, since it preserves pixel sizes:

def server = getCurrentServer()
def request = RegionRequest.createInstance(server)
def imp = IJTools.convertToImagePlus(server, request).getImage()
imp.show()

On the other hand

// Create whatever image ImageJ will give us (worked for color or 8-bit gray)
imp = new ImagePlus(title, img);

is a bad idea in general, and will often not work because ImageJ’s conversion may vary according to the image type (and sometimes color model). That’s why QuPath contains other, pixel-preserving methods.

Hi,
I am testing on 0.2.0-m2,and below is the full code:

import qupath.lib.scripting.QP;
import qupath.lib.regions.RegionRequest;
import qupath.imagej.helpers.IJTools;
def server = QP.getCurrentImageData().getServer();
def request = RegionRequest.createInstance("D:\\QMDownload\\9\\PyramidalCell-series-_Z001.tif",1,0,0,200,180,0,0);
def img = server.readBufferedImage(request);
def imp = IJTools.convertToUncalibratedImagePlus("Anything else",img);
imp.show();

The imp shows RGB image with no content: all pixel is black.

The second version also produce the same result:RGB image with no content.

import qupath.lib.scripting.QP;
import qupath.lib.regions.RegionRequest;
import qupath.imagej.helpers.IJTools;
def server = QP.getCurrentImageData().getServer();
def request = RegionRequest.createInstance("D:\\QMDownload\\9\\PyramidalCell-series-_Z001.tif",1,0,0,200,180,0,0);
def imp = IJTools.convertToImagePlus(server, request).getImage()
imp.show()
def imp_bitDepth = imp.getBitDepth();
println(".prim_nonRGB_var_imp_bitDepth = "+imp_bitDepth);

Ok, please include the version number from the beginning if it’s not the latest one.

Sorry, I can’t help with v0.2.0-m2. It works for me in v0.2.3, so any issue that might have existed in the early milestone pre-release from > 18 months ago has presumably been fixed.

2 Likes

That’s great! Both problems were solved in newest version of QuPath.
Thanks.