Imglib2 Scale2D/3D array index out of bounds exception

Edit: figured out the issue, there’s a specific dimension check much deeper into the processing of the Scale3D algorithm that separates the 2D and 3D images, and would fail with a 3D image with a z-dimension of 1. Just had to modify the code to ensure that 2D images were kept at only 2 dimensions.

Hello all,
I’m having an issue using the net.imglib2.script.algorithm.Scale3D or Scale 2D class when used with a 2D image causing an exception error:

java.lang.ArrayIndexOutOfBoundsException: 922880
	at net.imglib2.img.basictypeaccess.array.AbstractByteArray.getValue(AbstractByteArray.java:61)
	at net.imglib2.type.numeric.integer.GenericByteType.getByte(GenericByteType.java:127)
	at net.imglib2.type.numeric.integer.GenericByteType.set(GenericByteType.java:183)
	at net.imglib2.type.numeric.integer.GenericByteType.set(GenericByteType.java:51)
	at net.imglib2.interpolation.randomaccess.NLinearInterpolator.accumulate(NLinearInterpolator.java:264)
	at net.imglib2.interpolation.randomaccess.NLinearInterpolator.graycodeFwdRecursive(NLinearInterpolator.java:236)
	at net.imglib2.interpolation.randomaccess.NLinearInterpolator.get(NLinearInterpolator.java:205)
	at net.imglib2.interpolation.randomaccess.NLinearInterpolator.get(NLinearInterpolator.java:53)
	at net.imglib2.algorithm.transformation.ImageTransform.process(ImageTransform.java:219)
	at net.imglib2.script.algorithm.fn.AbstractAffine3D.processReal(AbstractAffine3D.java:200)
	at net.imglib2.script.algorithm.fn.AbstractAffine3D.process(AbstractAffine3D.java:123)
	at net.imglib2.script.algorithm.fn.AbstractAffine3D.<init>(AbstractAffine3D.java:74)
	at net.imglib2.script.algorithm.Affine3D.<init>(Affine3D.java:87)
	at net.imglib2.script.algorithm.Scale3D.<init>(Scale3D.java:67)
	at net.imglib2.script.algorithm.Scale3D.<init>(Scale3D.java:59)
	at CostesRandomizer.setNewImg(CostesRandomizer.java:105)
	at CostesRandomizer.<init>(CostesRandomizer.java:44)
	at Colocalization_by_Cross_Correlation.run(Colocalization_by_Cross_Correlation.java:175)
	at ij.IJ.runUserPlugIn(IJ.java:235)
	at ij.IJ.runPlugIn(IJ.java:198)
	at ij.Executer.runCommand(Executer.java:150)
	at ij.Executer.run(Executer.java:68)
	at java.lang.Thread.run(Thread.java:748)
java.lang.ArrayIndexOutOfBoundsExceptionThis text will be blurred

As of right now my plugin code is:

    public <T extends NumericType< T >> void setNewImg(Img <T> input, long[] inputPSFsize, Img <T> inputMask) {

        PSFsize = inputPSFsize.clone();

        RandomAccessibleInterval TDinputMask = inputMask.numDimensions() == 2 ? Views.addDimension(inputMask, 0, 0) : inputMask.copy();

        imageDimensions = new long[PSFsize.length];
        TDinputMask.dimensions(imageDimensions);

        source = input.copy();

        long [] bufferedDimensionsMax = new long[PSFsize.length];
        long [] bufferedDimensionsMin = new long[PSFsize.length];

        for (int i = 0; i < PSFsize.length; i++) {
            bufferedDimensionsMin[i] = 0;
            bufferedDimensionsMax[i] = imageDimensions[i]-1 + (imageDimensions[i]%PSFsize[i] == 0? 0 : PSFsize[i] - (imageDimensions[i]%PSFsize[i]));
        }

        showScaledImg(TDinputMask, "Scaled Image 0");

        RandomAccessibleInterval <T> extendedMaskTemp = Views.interval(Views.expandBorder(TDinputMask, PSFsize), bufferedDimensionsMin, bufferedDimensionsMax);

        showScaledImg(extendedMaskTemp, "Scaled Image 1");

        final Img<T> extendedMask = Util.getSuitableImgFactory(extendedMaskTemp, Util.getTypeFromInterval(extendedMaskTemp)).create(extendedMaskTemp);

        LoopBuilder.setImages(extendedMask, extendedMaskTemp).forEachPixel(Type::set);

        showScaledImg(extendedMask, "Scaled Image 2");

        Scale3D<T> scalar = null;

        try {
            scalar = new Scale3D<T>(extendedMask, 1.0/PSFsize[0], 1.0/PSFsize[1], 1.0/PSFsize[2]);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

This error occurs only when a 2D image is passed to the method (3D images work fine). It also doesn’t matter whether I used Scale2D or 3D (I also noticed Scale2D is the same as 3D with a fixed Z-scale value of 1), and the z value for PSFsize is 1 for any 2d image passed to the method. Also, the showScaledImg function is just for troubleshooting purposes, and all those images look as expected. Any guidance anyone could provide would be very helpful, as I cannot figure out what is causing this error.

1 Like

Hi @amccall ,

I can probably help, but may take some digging on my part. This is because I’m familiar with imglib2, I’m not so knowledgeable on net.imglib2.script.

Is it important to you to use the Scale3D class / function? or would you be open to me helping you write a function to do (hopefully) the same thing (but better if it doesn’t crash )

It’s worth fixing Scale3D, but unfortunately may be slower for me to fix it than for me to get you a workaround :-/

Edit:
Actually, could you also give the sizes of the input parameters that cause this error?

(Img <T> input, long[] inputPSFsize, Img <T> inputMask )

John

1 Like

Hi @bogovicj,

I actually got it working with the Scale3D class. There’s a step in the AffineTransform processing where it checks the image dimensions, and my 2D images were being passed through as 3D images with a z-dimension size of 1, which apparently the affine transformation didn’t like. I got it working now (I’ll paste the code below if you’re interested). However, if you have a better method I would be more than open to it. I was actually trying to find a binning function in the imglib2 library, as I am reducing the scale not increasing it, but I couldn’t find that anywhere.

New code:

public <T extends NumericType< T >> void setNewImg(Img <T> input, long[] inputPSFsize, Img <T> inputMask) {

        PSFsize = inputPSFsize.clone();

        imageDimensions = new long[inputMask.numDimensions()];
        inputMask.dimensions(imageDimensions);

        source = input.copy();

        long [] bufferedDimensionsMax = new long[inputMask.numDimensions()];
        long [] bufferedDimensionsMin = new long[inputMask.numDimensions()];

        for (int i = 0; i < inputMask.numDimensions(); i++) {
            bufferedDimensionsMin[i] = 0;
            bufferedDimensionsMax[i] = imageDimensions[i]-1 + (imageDimensions[i]%PSFsize[i] == 0? 0 : PSFsize[i] - (imageDimensions[i]%PSFsize[i]));
        }

        RandomAccessibleInterval <T> extendedMaskTemp = Views.interval(Views.expandBorder(inputMask, PSFsize), bufferedDimensionsMin, bufferedDimensionsMax);

        final Img<T> extendedMask = Util.getSuitableImgFactory(extendedMaskTemp, Util.getTypeFromInterval(extendedMaskTemp)).create(extendedMaskTemp);

        LoopBuilder.setImages(extendedMask, extendedMaskTemp).forEachPixel(Type::set);

        Scale3D<T> scalar = null;

        try {
            scalar = new Scale3D<T>(extendedMask, 1.0/PSFsize[0], 1.0/PSFsize[1], 1.0/PSFsize[2]);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }
1 Like