package de.danielsenff.imageflow.models.datatype; import ij.ImagePlus; import ij.plugin.filter.PlugInFilter; import java.awt.Dimension; import de.danielsenff.imageflow.models.connection.Input; import de.danielsenff.imageflow.models.connection.Output; import de.danielsenff.imageflow.models.connection.Pin; import de.danielsenff.imageflow.models.connection.ProxyOutput; import de.danielsenff.imageflow.models.unit.UnitElement; /** * Image-DataType. * This contains a definition for the ImageJ ImageTypes supported. * @author danielsenff * */ public class ImageDataType implements DataType { /** * defines the allowed ImageTypes used by ImageJ. */ protected int imageBitDepth; /** * Unit to which this DataType belongs */ protected UnitElement parent; /** * */ protected Pin parentPin; private Dimension dimension; /** * @param imageBitDepth * @param width * @param height */ public ImageDataType(final int imageBitDepth, final int width, final int height) { this.imageBitDepth = imageBitDepth; this.setDimension(new Dimension(width, height)); } /** * @param imageBitDepth */ public ImageDataType(final int imageBitDepth) { this.imageBitDepth = imageBitDepth; this.setDimension(new Dimension()); } /** * @param bitDepth */ public void setImageBitDepth(final int bitDepth) { this.imageBitDepth = bitDepth; } /** * Gets the Images bitdepth. * @return */ public int getImageBitDepth() { if(this.imageBitDepth > 0 && this.imageBitDepth != PlugInFilter.DOES_ALL) { return this.imageBitDepth; } else if(parentPin instanceof ProxyOutput) { // instead of looking at our own parent to get a valid image type from an input // we look at the parent of the embedded pin, thereby bubbling through // the internal list of the group UnitElement parent = ((ProxyOutput)parentPin).getEmbeddedOutput().getParent(); //TODO this could be nicer, how to handle multiple inputs? if(parent.hasInputsConnected()) { for (Input input : parent.getInputs()) { if(input.isConnected() && input.getDataType() instanceof ImageDataType) { int inheritedBitDepth = ((ImageDataType)input.getFromOutput().getDataType()).getImageBitDepth(); // if -2 then convert from stack to image inheritedBitDepth -= this.imageBitDepth == -2 ? PlugInFilter.DOES_STACKS : 0; return inheritedBitDepth; } } return -1; } } else if(parentPin instanceof Output) { //TODO this could be nicer, how to handle multiple inputs? if(parent.hasInputsConnected()) { for (Input input : parent.getInputs()) { if(input.isConnected() && input.getDataType() instanceof ImageDataType) { int inheritedBitDepth = ((ImageDataType)input.getFromOutput().getDataType()).getImageBitDepth(); inheritedBitDepth -= this.imageBitDepth == -2 ? PlugInFilter.DOES_STACKS : 0; return inheritedBitDepth; } } return -1; } } // this means our output doesn't know his own capabilities // and because it has no inputs, it can't get them anywhere // this sucks return this.imageBitDepth; } public String getSimpleName() { return "Image"; } public String getName() { return "Image ("+getVerboseImageFormat()+")"; } private String getVerboseImageFormat() { switch(getImageBitDepth()) { case PlugInFilter.DOES_8G: return "8-bit grayscale"; case PlugInFilter.DOES_16: return "16-bit grayscale"; case PlugInFilter.DOES_32: return "32-bit floating-point grayscale"; case PlugInFilter.DOES_8C: return "8-bit indexed color"; case PlugInFilter.DOES_RGB: return "32-bit RGB color"; case PlugInFilter.DOES_ALL: return "ambigous type"; } return "unknown"; } public boolean isCompatible(DataType compareType) { if(compareType instanceof ImageDataType) return isImageBitDepthCompatible(((ImageDataType) compareType).getImageBitDepth()); return false; } /** * Returns true, if the imageBitDepth in question is supported * by this Input. * @param foreignImageBitDepth * @return */ public boolean isImageBitDepthCompatible(final int foreignImageBitDepth) { int ownImageBitDepth = getImageBitDepth(); if(ownImageBitDepth != -1 && foreignImageBitDepth != -1) { int remain = ownImageBitDepth&foreignImageBitDepth; /* * if 0 -> it doesn't fit * if value, we got a match */ return remain != 0; } return false; } /** * @param parent */ public void setParentUnitElement(final UnitElement parent) { this.parent = parent; } @Override public String toString() { return super.toString() + " ParentPin: "+parentPin.getDisplayName(); } /** * @param pin */ public void setParentPin(Pin pin) { this.parentPin = pin; } @Override public ImageDataType clone() { ImageDataType image = new ImageDataType(this.imageBitDepth); return image; } public void setDimension(Dimension dimension) { this.dimension = dimension; } public Dimension getDimension() { return dimension; } public int getWidth() { return this.dimension.width; } public int getHeight() { return this.dimension.height; } }