use of ij.process.ShortProcessor in project bioformats by openmicroscopy.
the class ImageProcessorReader method openThumbProcessors.
public ImageProcessor[] openThumbProcessors(int no) throws FormatException, IOException {
// read byte array
byte[] b = openThumbBytes(no);
int c = getRGBChannelCount();
int type = getPixelType();
int bpp = FormatTools.getBytesPerPixel(type);
boolean interleave = isInterleaved();
int w = getThumbSizeX();
int h = getThumbSizeY();
if (b.length != w * h * c * bpp && b.length != w * h * bpp) {
throw new FormatException("Invalid byte array length: " + b.length + " (expected w=" + w + ", h=" + h + ", c=" + c + ", bpp=" + bpp + ")");
}
// create a color model for this plane (null means default)
final LUT cm = createColorModel();
// convert byte array to appropriate primitive array type
boolean isFloat = FormatTools.isFloatingPoint(type);
boolean isLittle = isLittleEndian();
boolean isSigned = FormatTools.isSigned(type);
// construct image processors
ImageProcessor[] ip = new ImageProcessor[c];
for (int i = 0; i < c; i++) {
byte[] channel = ImageTools.splitChannels(b, i, c, bpp, false, interleave);
Object pixels = DataTools.makeDataArray(channel, bpp, isFloat, isLittle);
if (pixels instanceof byte[]) {
byte[] q = (byte[]) pixels;
if (q.length != w * h) {
byte[] tmp = q;
q = new byte[w * h];
System.arraycopy(tmp, 0, q, 0, Math.min(q.length, tmp.length));
}
if (isSigned)
q = DataTools.makeSigned(q);
ip[i] = new ByteProcessor(w, h, q, null);
if (cm != null)
ip[i].setColorModel(cm);
} else if (pixels instanceof short[]) {
short[] q = (short[]) pixels;
if (q.length != w * h) {
short[] tmp = q;
q = new short[w * h];
System.arraycopy(tmp, 0, q, 0, Math.min(q.length, tmp.length));
}
if (isSigned)
q = DataTools.makeSigned(q);
ip[i] = new ShortProcessor(w, h, q, cm);
} else if (pixels instanceof int[]) {
int[] q = (int[]) pixels;
if (q.length != w * h) {
int[] tmp = q;
q = new int[w * h];
System.arraycopy(tmp, 0, q, 0, Math.min(q.length, tmp.length));
}
ip[i] = new FloatProcessor(w, h, q);
} else if (pixels instanceof float[]) {
float[] q = (float[]) pixels;
if (q.length != w * h) {
float[] tmp = q;
q = new float[w * h];
System.arraycopy(tmp, 0, q, 0, Math.min(q.length, tmp.length));
}
ip[i] = new FloatProcessor(w, h, q, null);
} else if (pixels instanceof double[]) {
double[] q = (double[]) pixels;
if (q.length != w * h) {
double[] tmp = q;
q = new double[w * h];
System.arraycopy(tmp, 0, q, 0, Math.min(q.length, tmp.length));
}
ip[i] = new FloatProcessor(w, h, q);
}
}
return ip;
}
use of ij.process.ShortProcessor in project bioformats by openmicroscopy.
the class RecordedImageProcessor method createImage.
@Override
public Image createImage() {
if (otherChannels == null)
return proc.createImage();
// merge channels - adapted from CompositeImage
int size = proc.getWidth() * proc.getHeight();
int[] rgbPixels = new int[size];
for (int i = 0; i < otherChannels.length + 1; i++) {
ImageProcessor activeProcessor = null;
if (i == channelNumber) {
activeProcessor = proc;
} else {
if (i < channelNumber)
activeProcessor = otherChannels[i];
else
activeProcessor = otherChannels[i - 1];
}
IndexColorModel cm = (IndexColorModel) activeProcessor.getColorModel();
int mapSize = cm.getMapSize();
int[] reds = new int[mapSize];
int[] greens = new int[mapSize];
int[] blues = new int[mapSize];
byte[] tmp = new byte[mapSize];
cm.getReds(tmp);
for (int q = 0; q < mapSize; q++) {
reds[q] = (tmp[q] & 0xff) << 16;
}
cm.getGreens(tmp);
for (int q = 0; q < mapSize; q++) {
greens[q] = (tmp[q] & 0xff) << 8;
}
cm.getBlues(tmp);
for (int q = 0; q < mapSize; q++) {
blues[q] = tmp[q] & 0xff;
}
byte[] pixels = new byte[size];
double min = activeProcessor.getMin();
double max = activeProcessor.getMax();
double scale = 256.0 / (max - min + 1);
if (activeProcessor instanceof ByteProcessor) {
pixels = (byte[]) activeProcessor.getPixels();
} else if (activeProcessor instanceof ShortProcessor) {
short[] s = (short[]) activeProcessor.getPixels();
for (int q = 0; q < size; q++) {
int value = (int) ((s[q] & 0xffff) - min);
if (value < 0)
value = 0;
value = (int) (value * scale + 0.5);
if (value > 255)
value = 255;
pixels[q] = (byte) value;
}
} else if (activeProcessor instanceof FloatProcessor) {
float[] f = (float[]) activeProcessor.getPixels();
for (int q = 0; q < size; q++) {
float value = (float) (f[q] - min);
if (value < 0)
value = 0f;
int ivalue = (int) (value * scale);
if (ivalue > 255)
ivalue = 255;
pixels[q] = (byte) ivalue;
}
}
switch(i) {
case 0:
for (int q = 0; q < size; q++) {
rgbPixels[q] = (rgbPixels[q] & 0xff00ffff) | reds[pixels[q] & 0xff];
}
break;
case 1:
for (int q = 0; q < size; q++) {
rgbPixels[q] = (rgbPixels[q] & 0xffff00ff) | greens[pixels[q] & 0xff];
}
break;
case 2:
for (int q = 0; q < size; q++) {
rgbPixels[q] = (rgbPixels[q] & 0xffffff00) | blues[pixels[q] & 0xff];
}
break;
case 3:
for (int q = 0; q < size; q++) {
int red = reds[pixels[q] & 0xff];
int green = greens[pixels[q] & 0xff];
int blue = blues[pixels[q] & 0xff];
rgbPixels[q] = red | green | blue;
}
break;
default:
for (int q = 0; q < size; q++) {
int pixel = rgbPixels[q];
int red = (pixel & 0xff0000) + reds[pixels[q] & 0xff];
int green = (pixel & 0x00ff00) + greens[pixels[q] & 0xff];
int blue = (pixel & 0xff) + blues[pixels[q] & 0xff];
if (red > 16711680)
red = 16711680;
if (green > 65280)
green = 65280;
if (blue > 255)
blue = 255;
rgbPixels[q] = red | green | blue;
}
}
}
DirectColorModel rgb = new DirectColorModel(32, 0xff0000, 0xff00, 0xff);
MemoryImageSource src = new MemoryImageSource(proc.getWidth(), proc.getHeight(), rgb, rgbPixels, 0, proc.getWidth());
src.setAnimated(true);
src.setFullBufferUpdates(true);
return Toolkit.getDefaultToolkit().createImage(src);
}
use of ij.process.ShortProcessor in project mcib3d-core by mcib3d.
the class ImageShort method resize.
@Override
public ImageHandler resize(int dX, int dY, int dZ) {
int newX = Math.max(1, sizeX + 2 * dX);
int newY = Math.max(1, sizeY + 2 * dY);
// boolean bck = Prefs.get("resizer.zero", true);
// Prefs.set("resizer.zero", true);
ij.plugin.CanvasResizer cr = new ij.plugin.CanvasResizer();
ImageStack res = cr.expandStack(img.duplicate().getStack(), newX, newY, dX, dY);
// }
if (dZ > 0) {
for (int i = 0; i < dZ; i++) {
res.addSlice("", new ShortProcessor(newX, newY), 0);
res.addSlice("", new ShortProcessor(newX, newY));
}
} else {
for (int i = 0; i < -dZ; i++) {
if (res.getSize() <= 2) {
break;
}
res.deleteLastSlice();
res.deleteSlice(1);
}
}
ImageShort r = new ImageShort(new ImagePlus(title + "::resized", res));
r.offsetX = offsetX - dX;
r.offsetY = offsetY - dY;
r.offsetZ = offsetZ - dZ;
return r;
}
use of ij.process.ShortProcessor in project TrakEM2 by trakem2.
the class AreaList method exportAsLabels.
/**
* Export all given AreaLists as one per pixel value, what is called a "labels" file; a file dialog is offered to save the image as a tiff stack.
*/
public static void exportAsLabels(final List<Displayable> listToPaint, final ij.gui.Roi roi, final float scale, int first_layer, int last_layer, final boolean visible_only, final boolean to_file, final boolean as_amira_labels) {
// survive everything:
if (null == listToPaint || 0 == listToPaint.size()) {
Utils.log("Null or empty list.");
return;
}
if (scale < 0 || scale > 1) {
Utils.log("Improper scale value. Must be 0 < scale <= 1");
return;
}
// Select the subset to paint
final ArrayList<AreaList> list = new ArrayList<AreaList>();
for (final Displayable d : listToPaint) {
if (visible_only && !d.isVisible())
continue;
if (d instanceof AreaList)
list.add((AreaList) d);
}
Utils.log2("exportAsLabels: list.size() is " + list.size());
// Current AmiraMeshEncoder supports ByteProcessor only: 256 labels max, including background at zero.
if (as_amira_labels && list.size() > 255) {
Utils.log("Saving ONLY first 255 AreaLists!\nDiscarded:");
final StringBuilder sb = new StringBuilder();
for (final Displayable d : list.subList(255, list.size())) {
sb.append(" ").append(d.getProject().getShortMeaningfulTitle(d)).append('\n');
}
Utils.log(sb.toString());
final ArrayList<AreaList> li = new ArrayList<AreaList>(list);
list.clear();
list.addAll(li.subList(0, 255));
}
String path = null;
if (to_file) {
final String ext = as_amira_labels ? ".am" : ".tif";
final File f = Utils.chooseFile("labels", ext);
if (null == f)
return;
path = f.getAbsolutePath().replace('\\', '/');
}
final LayerSet layer_set = list.get(0).getLayerSet();
if (first_layer > last_layer) {
final int tmp = first_layer;
first_layer = last_layer;
last_layer = tmp;
if (first_layer < 0)
first_layer = 0;
if (last_layer >= layer_set.size())
last_layer = layer_set.size() - 1;
}
// Create image according to roi and scale
final int width, height;
final Rectangle broi;
if (null == roi) {
broi = null;
width = (int) (layer_set.getLayerWidth() * scale);
height = (int) (layer_set.getLayerHeight() * scale);
} else {
broi = roi.getBounds();
width = (int) (broi.width * scale);
height = (int) (broi.height * scale);
}
// Compute highest label value, which affects of course the stack image type
final TreeSet<Integer> label_values = new TreeSet<Integer>();
for (final Displayable d : list) {
final String label = d.getProperty("label");
if (null != label)
label_values.add(Integer.parseInt(label));
}
int lowest = 0, highest = 0;
if (label_values.size() > 0) {
lowest = label_values.first();
highest = label_values.last();
}
final int n_non_labeled = list.size() - label_values.size();
final int max_label_value = highest + n_non_labeled;
int type_ = ImagePlus.GRAY8;
if (max_label_value > 255) {
type_ = ImagePlus.GRAY16;
if (max_label_value > 65535) {
type_ = ImagePlus.GRAY32;
}
}
final int type = type_;
final ImageStack stack = new ImageStack(width, height);
final Calibration cal = layer_set.getCalibration();
String amira_params = null;
if (as_amira_labels) {
final StringBuilder sb = new StringBuilder("CoordType \"uniform\"\nMaterials {\nExterior {\n Id 0,\nColor 0 0 0\n}\n");
final float[] c = new float[3];
int value = 0;
for (final Displayable d : list) {
// 0 is background
value++;
d.getColor().getRGBColorComponents(c);
String s = d.getProject().getShortMeaningfulTitle(d);
s = s.replace('-', '_').replaceAll(" #", " id");
sb.append(Utils.makeValidIdentifier(s)).append(" {\n").append("Id ").append(value).append(",\n").append("Color ").append(c[0]).append(' ').append(c[1]).append(' ').append(c[2]).append("\n}\n");
}
sb.append("}\n");
amira_params = sb.toString();
}
final float len = last_layer - first_layer + 1;
// Assign labels
final HashMap<AreaList, Integer> labels = new HashMap<AreaList, Integer>();
for (final AreaList d : list) {
final String slabel = d.getProperty("label");
int label;
if (null != slabel) {
label = Integer.parseInt(slabel);
} else {
// 0 is background
label = (++highest);
}
labels.put(d, label);
}
final ExecutorService exec = Utils.newFixedThreadPool("labels");
final Map<Integer, ImageProcessor> slices = Collections.synchronizedMap(new TreeMap<Integer, ImageProcessor>());
final List<Future<?>> fus = new ArrayList<Future<?>>();
final List<Layer> layers = layer_set.getLayers().subList(first_layer, last_layer + 1);
for (int k = 0; k < layers.size(); k++) {
final Layer la = layers.get(k);
final int slice = k;
fus.add(exec.submit(new Runnable() {
@Override
public void run() {
Utils.showProgress(slice / len);
final ImageProcessor ip;
if (ImagePlus.GRAY8 == type) {
final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
final Graphics2D g = bi.createGraphics();
for (final AreaList ali : list) {
final Area area = ali.getArea(la);
if (null == area || area.isEmpty())
continue;
// Transform: the scale and the roi
final AffineTransform aff = new AffineTransform();
/* 3 - To scale: */
if (1 != scale)
aff.scale(scale, scale);
/* 2 - To roi coordinates: */
if (null != broi)
aff.translate(-broi.x, -broi.y);
/* 1 - To world coordinates: */
aff.concatenate(ali.at);
g.setTransform(aff);
final int label = labels.get(ali);
g.setColor(new Color(label, label, label));
g.fill(area);
}
g.dispose();
ip = new ByteProcessor(bi);
bi.flush();
} else if (ImagePlus.GRAY16 == type) {
final USHORTPaint paint = new USHORTPaint((short) 0);
final BufferedImage bi = new BufferedImage(paint.getComponentColorModel(), paint.getComponentColorModel().createCompatibleWritableRaster(width, height), false, null);
final Graphics2D g = bi.createGraphics();
// final ColorSpace ugray = ColorSpace.getInstance(ColorSpace.CS_GRAY);
int painted = 0;
for (final AreaList ali : list) {
final Area area = ali.getArea(la);
if (null == area || area.isEmpty())
continue;
// Transform: the scale and the roi
final AffineTransform aff = new AffineTransform();
/* 3 - To scale: */
if (1 != scale)
aff.scale(scale, scale);
/* 2 - To roi coordinates: */
if (null != broi)
aff.translate(-broi.x, -broi.y);
/* 1 - To world coordinates: */
aff.concatenate(ali.at);
// Fill
g.setTransform(aff);
// The color doesn't work: paints in a stretched 8-bit mode
// g.setColor(new Color(ugray, new float[]{((float)labels.get(d)) / range}, 1));
Utils.log2("value: " + labels.get(ali).shortValue());
paint.setValue(labels.get(ali).shortValue());
g.setPaint(paint);
// .createTransformedArea(aff));
g.fill(area);
painted += 1;
}
g.dispose();
ip = new ShortProcessor(bi);
bi.flush();
Utils.log2("painted: " + painted);
} else {
// Option 1: could use the same as above, but shifted by 65536, so that 65537 is 1, 65538 is 2, etc.
// and keep doing it until no more need to be shifted.
// The PROBLEM: cannot keep the order without complicated gymnastics to remember
// which label in which image has to be merged to the final image, which prevent
// a simple one-pass blitter.
//
// Option 2: paint each arealist, extract the image, use it as a mask for filling:
final FloatProcessor fp = new FloatProcessor(width, height);
final float[] fpix = (float[]) fp.getPixels();
ip = fp;
final BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
final Graphics2D gbi = bi.createGraphics();
for (final AreaList ali : list) {
final Area area = ali.getArea(la);
if (null == area || area.isEmpty()) {
continue;
}
// Transform: the scale and the roi
// reverse order of transformations:
final AffineTransform aff = new AffineTransform();
/* 3 - To scale: */
if (1 != scale)
aff.scale(scale, scale);
/* 2 - To ROI coordinates: */
if (null != broi)
aff.translate(-broi.x, -broi.y);
/* 1 - To world coordinates: */
aff.concatenate(ali.at);
final Area s = area.createTransformedArea(aff);
final Rectangle sBounds = s.getBounds();
// Need to paint at all?
if (0 == sBounds.width || 0 == sBounds.height || !sBounds.intersects(0, 0, width, height))
continue;
// Paint shape
gbi.setColor(Color.white);
gbi.fill(s);
// Read out painted region
final int x0 = Math.max(0, sBounds.x);
final int y0 = Math.max(0, sBounds.y);
final int xN = Math.min(width, sBounds.x + sBounds.width);
final int yN = Math.min(height, sBounds.y + sBounds.height);
// Get the array
final byte[] bpix = ((DataBufferByte) bi.getRaster().getDataBuffer()).getData();
final float value = labels.get(ali);
// For every non-black pixel, set a 'value' pixel in the FloatProcessor
for (int y = y0; y < yN; ++y) {
for (int x = x0; x < xN; ++x) {
final int pos = y * width + x;
// black
if (0 == bpix[pos])
continue;
fpix[pos] = value;
}
}
// Clear image region
gbi.setColor(Color.black);
gbi.fill(s);
}
gbi.dispose();
bi.flush();
}
slices.put(slice, ip);
}
}));
}
Utils.wait(fus);
exec.shutdownNow();
for (final Map.Entry<Integer, ImageProcessor> e : slices.entrySet()) {
final Layer la = layers.get(e.getKey());
stack.addSlice(la.getZ() * cal.pixelWidth + "", e.getValue());
if (ImagePlus.GRAY8 != type) {
e.getValue().setMinAndMax(lowest, highest);
}
}
Utils.showProgress(1);
// Save via file dialog:
final ImagePlus imp = new ImagePlus("Labels", stack);
if (as_amira_labels)
imp.setProperty("Info", amira_params);
imp.setCalibration(layer_set.getCalibrationCopy());
if (to_file) {
if (as_amira_labels) {
final AmiraMeshEncoder ame = new AmiraMeshEncoder(path);
if (!ame.open()) {
Utils.log("Could not write to file " + path);
return;
}
if (!ame.write(imp)) {
Utils.log("Error in writing Amira file!");
return;
}
} else {
new FileSaver(imp).saveAsTiff(path);
}
} else
imp.show();
}
use of ij.process.ShortProcessor in project TrakEM2 by trakem2.
the class Downsampler method downsampleShort.
/**
* Create a downsampled version of a {@link ShortProcessor} and the
* mapping of its [min,max] range into an unsigned byte array.
*
* @param a
* @return
* Pair.a downsampled {@link ShortProcessor}
* Pair.b mapped into unsigned byte
*/
public static final Pair<ShortProcessor, byte[]> downsampleShort(final ShortProcessor a) {
final int wa = a.getWidth();
final int ha = a.getHeight();
final int wa2 = wa + wa;
final double min = a.getMin();
final double max = a.getMax();
final double scale = 255.0 / (max - min);
final int wb = wa / 2;
final int hb = ha / 2;
final int nb = hb * wb;
final ShortProcessor b = new ShortProcessor(wb, hb);
b.setMinAndMax(min, max);
final short[] aPixels = (short[]) a.getPixels();
final short[] bPixels = (short[]) b.getPixels();
final byte[] bBytes = new byte[bPixels.length];
for (int ya = 0, yb = 0; yb < nb; ya += wa2, yb += wb) {
final int ya1 = ya + wa;
for (int xa = 0, xb = 0; xb < wb; xa += 2, ++xb) {
final int xa1 = xa + 1;
final int yaxa = ya + xa;
final int yaxa1 = ya + xa1;
final int ya1xa = ya1 + xa;
final int ya1xa1 = ya1 + xa1;
final int ybxb = yb + xb;
final int s = averageShort(yaxa, yaxa1, ya1xa, ya1xa1, aPixels);
bPixels[ybxb] = (short) s;
final int sb = (int) ((s - min) * scale + 0.5);
bBytes[ybxb] = (byte) (sb < 0 ? 0 : sb > 255 ? 255 : sb);
}
}
return new Pair<ShortProcessor, byte[]>(b, bBytes);
}
Aggregations