Posted by
ctrueden on
Oct 10, 2008; 4:38pm
URL: http://imagej.273.s1.nabble.com/Handle-multiple-bit-depths-tp3694774p3694776.html
Hi Mike,
Unfortunately, this issue stems from a limitation with Java primitive types.
The typical way to handle it is to use case logic. In your example, it would
look something like:
Object pix = stack.getPixels(s);
if (pix instanceof byte[]) {
byte[] pixels = (byte[]) pix;
for (int y=r.y; y<(r.y+r.height); y++) {
offset = y*w;
for (int x=r.x; x<(r.x+r.width); x++) {
i = offset + x;
if (pixels[i] >= minT && pixels[i] <= maxT) volBone++;
}
}
}else if (pix instanceof short[]) {
short[] pixels = (short[]) pix;
for (int y=r.y; y<(r.y+r.height); y++) {
offset = y*w;
for (int x=r.x; x<(r.x+r.width); x++) {
i = offset + x;
if (pixels[i] >= minT && pixels[i] <= maxT) volBone++;
}
}
}
else if (pix instanceof int[]) {
int[] pixels = (int[]) pix;
for (int y=r.y; y<(r.y+r.height); y++) {
offset = y*w;
for (int x=r.x; x<(r.x+r.width); x++) {
i = offset + x;
if (pixels[i] >= minT && pixels[i] <= maxT) volBone++;
} }
}
else if (pix instanceof float[]) {
float[] pixels = (float[]) pix;
for (int y=r.y; y<(r.y+r.height); y++) {
offset = y*w;
for (int x=r.x; x<(r.x+r.width); x++) {
i = offset + x;
if (pixels[i] >= minT && pixels[i] <= maxT) volBone++;
}
}
}
else {
System.out.println("Unsupported pixel type: " + pix.getClass().getName());
}
If you look at the AVI_Reader as Reinhard suggests, you'll see that it also
uses case logic (unpack8bit, unpackGray, unpackShort, etc.).
An alternative would be to use reflection (one of Java's strengths) to
handle it, but I'm not sure if it is as efficient as the case-by-case code.
Give it a try and find out:
import java.lang.reflect.Array;
...
Object pixels = stack.getPixels(s);
for (int y=r.y; y<(r.y+r.height); y++) {
offset = y*w;
for (int x=r.x; x<(r.x+r.width); x++) {
i = offset + x;
double val = Array.getDouble(pixels, i);
if (val >= minT && val <= maxT) volBone++;
}
}
There may be some other slick way to handle this in Java 1.6+, as I haven't
kept up with the newest language features, but somehow I doubt it.
-Curtis
On Fri, Oct 10, 2008 at 11:11 AM, Michael Doube <
[hidden email]>wrote:
> Hi all
>
> How do I handle multiple bit depths in a plugin? I am writing a
> super-simple plugin to calculate volume fraction, which is just the ratio of
> thresholded pixels to all pixels in a selected volume. I've tried a few
> things, but always get caught out by declaring the pixels[] array in an if
> statement like:
>
> if (imp.getBitDepth == 8){byte[] pixels = (byte[])stack.getPixels(s)};
>
> or by casting in a wrong way. I've looked around for examples but haven't
> come up with much.
>
> Cheers
>
> Mike
> ---------------
> /*Volume fraction of Bone
> * Plugin to calculate volume fraction in stacks
> */
>
> import java.awt.Rectangle;
> import ij.IJ;
> import ij.ImagePlus;
> import ij.ImageStack;
> import ij.process.ImageProcessor;
> import ij.plugin.filter.PlugInFilter;
> import ij.measure.ResultsTable;
> import ij.gui.*;
>
> public class Volume_Fraction implements PlugInFilter {
> ImagePlus imp;
> protected ImageStack stack;
>
> public int setup(String arg, ImagePlus imp) {
> stack = imp.getStack();
> this.imp = imp;
> return DOES_8G + DOES_16 + DOES_32 + STACK_REQUIRED;
> }
> public void run(ImageProcessor ip) {
> ResultsTable rt = ResultsTable.getResultsTable();
> rt.reset();
> String title = imp.getTitle();
> IJ.run("Threshold...");
> new WaitForUserDialog("Set the threshold, then click OK.").show();
> short minT = (short)ip.getMinThreshold();
> short maxT = (short)ip.getMaxThreshold();
> int startSlice = 1;
> int endSlice = stack.getSize();
> int w = stack.getWidth();
> GenericDialog gd = new GenericDialog("Limit Slices");
> gd.addNumericField("Start Slice:",startSlice,0);
> gd.addNumericField("End Slice:",endSlice,0);
> gd.showDialog();
> if (gd.wasCanceled()) {
> IJ.error("PlugIn canceled!");
> return;
> }
> startSlice = (int)gd.getNextNumber();
> endSlice = (int)gd.getNextNumber();
> Rectangle r = ip.getRoi();
> int volTotal = r.height * r.width * (endSlice - startSlice +
> 1);
> int offset, i;
> int volBone = 0;
> for (int s=startSlice;s<=endSlice;s++) {
> double[] pixels = (double[])stack.getPixels(s);
> for (int y=r.y; y<(r.y+r.height); y++) {
> offset = y*w;
> for (int x=r.x; x<(r.x+r.width); x++) {
> i = offset + x;
> if (pixels[i] >= minT && pixels[i] <= maxT){
> volBone++;
> }
> }
> }
> }
> double p = (double) volBone / volTotal;
> rt.incrementCounter();
> rt.addLabel("Label", title);
> rt.addValue("VfB", p);
> rt.show("Results");
> }
> }
>