Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

group = "io.github.qupath"
version = "0.1.0"
version = "0.1.1"

repositories {
mavenCentral()
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/qupath/ext/imglib2/AccessibleScaler.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import net.imglib2.RandomAccessible;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.interpolation.InterpolatorFactory;
import net.imglib2.interpolation.randomaccess.NLinearInterpolatorFactory;
import net.imglib2.interpolation.randomaccess.NearestNeighborInterpolatorFactory;
import net.imglib2.realtransform.AffineGet;
import net.imglib2.realtransform.RealViews;
import net.imglib2.realtransform.Scale2D;
import net.imglib2.realtransform.Translation2D;
import net.imglib2.type.numeric.NumericType;
import net.imglib2.view.Views;
import qupath.ext.imglib2.interpolators.LinearInterpolationFactory;

import java.util.Arrays;
import java.util.stream.LongStream;
Expand All @@ -35,15 +35,17 @@ private AccessibleScaler() {
* @param scale the scale to apply to the first two dimensions of the input {@link RandomAccessibleInterval}. Shouldn't be
* less than or equal to 0
* @return the input if the provided scale is 1, or a new scaled {@link RandomAccessibleInterval} otherwise
* @param <T> the type of elements of the random accessible interval
* @param <T> the type of elements of the random accessible interval. It must be {@link net.imglib2.type.numeric.ARGBType}
* or an instance of {@link net.imglib2.type.numeric.RealType}, otherwise a {@link IllegalArgumentException}
* will be thrown when accessing the output
* @throws IllegalArgumentException if the input interval has at least one minimum different from 0, if the provided scale is less
* than or equal to 0, or if the input interval has less than two dimensions
*/
public static <T extends NumericType<T>> RandomAccessibleInterval<T> scaleWithLinearInterpolation(
RandomAccessibleInterval<T> input,
double scale
) {
return scale(input, scale, new NLinearInterpolatorFactory<>());
return scale(input, scale, new LinearInterpolationFactory<>());
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package qupath.ext.imglib2.interpolators;

import net.imglib2.RandomAccessible;
import net.imglib2.interpolation.randomaccess.NLinearInterpolator2D;
import net.imglib2.type.numeric.ARGBType;

/**
* A {@link NLinearInterpolator2D} that performs intermediary operations with doubles, to avoid precision errors.
*/
class ArgbLinearInterpolator extends NLinearInterpolator2D<ARGBType> {

/**
* Create an instance of this class.
*
* @param randomAccessible the accessible to interpolate
*/
public ArgbLinearInterpolator(RandomAccessible<ARGBType> randomAccessible) {
super(randomAccessible);
}

@Override
public ARGBType get()
{
fillWeights();

int pixelValue;
double red = 0;
double green = 0;
double blue = 0;
double alpha = 0;

pixelValue = target.get().get();
red += ARGBType.red(pixelValue) * weights[0];
green += ARGBType.green(pixelValue) * weights[0];
blue += ARGBType.blue(pixelValue) * weights[0];
alpha += ARGBType.alpha(pixelValue) * weights[0];

target.fwd(0);
pixelValue = target.get().get();
red += ARGBType.red(pixelValue) * weights[1];
green += ARGBType.green(pixelValue) * weights[1];
blue += ARGBType.blue(pixelValue) * weights[1];
alpha += ARGBType.alpha(pixelValue) * weights[1];

target.fwd(1);
pixelValue = target.get().get();
red += ARGBType.red(pixelValue) * weights[3];
green += ARGBType.green(pixelValue) * weights[3];
blue += ARGBType.blue(pixelValue) * weights[3];
alpha += ARGBType.alpha(pixelValue) * weights[3];

target.bck(0);
pixelValue = target.get().get();
red += ARGBType.red(pixelValue) * weights[2];
green += ARGBType.green(pixelValue) * weights[2];
blue += ARGBType.blue(pixelValue) * weights[2];
alpha += ARGBType.alpha(pixelValue) * weights[2];

target.bck(1);

accumulator.set(ARGBType.rgba(red, green, blue, alpha));

return accumulator;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package qupath.ext.imglib2.interpolators;

import net.imglib2.RandomAccessible;
import net.imglib2.RealInterval;
import net.imglib2.RealRandomAccess;
import net.imglib2.interpolation.InterpolatorFactory;
import net.imglib2.type.numeric.ARGBType;
import net.imglib2.type.numeric.NumericType;
import net.imglib2.type.numeric.RealType;

/**
* An {@link InterpolatorFactory} that implements a 2D linear interpolation.
* <p>
* This factory can only work with {@link RandomAccessible} that have 2 dimensions and the {@link ARGBType} or {@link RealType}
* type. If {@link #create(RandomAccessible)} is called with an invalid {@link RandomAccessible}, an {@link IllegalArgumentException}
* is thrown.
*
* @param <T> the type of {@link RandomAccessible} to interpolate
*/
public class LinearInterpolationFactory<T extends NumericType<T>> implements InterpolatorFactory<T, RandomAccessible<T>> {

@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public RealRandomAccess<T> create(RandomAccessible randomAccessible) {
if (randomAccessible.numDimensions() != 2) {
throw new IllegalArgumentException(String.format(
"The provided accessible has not 2 dimensions (found %d)",
randomAccessible.numDimensions()
));
}

Object type = randomAccessible.randomAccess().get();
if (type instanceof ARGBType) {
return (RealRandomAccess<T>) new ArgbLinearInterpolator(randomAccessible);
} else if (type instanceof RealType<?>) {
return (RealRandomAccess<T>) new RealLinearInterpolator<>(randomAccessible);
} else {
throw new IllegalArgumentException(String.format(
"The type of the provided accessible %s is unexpected",
type
));
}
}

@Override
public RealRandomAccess<T> create(RandomAccessible<T> randomAccessible, RealInterval interval) {
return create(randomAccessible);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package qupath.ext.imglib2.interpolators;

import net.imglib2.RandomAccessible;
import net.imglib2.interpolation.randomaccess.NLinearInterpolator2D;
import net.imglib2.type.numeric.RealType;

/**
* A {@link NLinearInterpolator2D} that performs intermediary operations with doubles, to avoid precision errors.
*/
class RealLinearInterpolator<T extends RealType<T>> extends NLinearInterpolator2D<T> {

/**
* Create an instance of this class.
*
* @param randomAccessible the accessible to interpolate
*/
public RealLinearInterpolator(RandomAccessible<T> randomAccessible) {
super(randomAccessible);
}

@Override
public T get()
{
fillWeights();

double value = target.get().getRealDouble() * weights[0];

target.fwd(0);
value += target.get().getRealDouble() * weights[1];

target.fwd(1);
value += target.get().getRealDouble() * weights[3];

target.bck(0);
value += target.get().getRealDouble() * weights[2];

target.bck(1);

accumulator.setReal(value);

return accumulator;
}
}
Loading