imageJ.Colour_Deconvolution Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of orbit-image-analysis Show documentation
Show all versions of orbit-image-analysis Show documentation
Orbit, a versatile image analysis software for biological image-based quantification
package imageJ;
import com.actelion.research.orbit.gui.ImagePane;
import com.actelion.research.orbit.utils.RawUtilsCommon;
import ij.ImagePlus;
import ij.ImageStack;
import ij.WindowManager;
import ij.plugin.PlugIn;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.io.File;
public class Colour_Deconvolution implements PlugIn {
// G.Landini at bham ac uk
// 30/Mar/2004 released
// 03/Apr/2004 resolved ROI exiting
// 07/Apr/2004 added Methyl Green DAB vectors
// 08/Jul/2004 shortened the code
// 01/Aug/2005 added fast red/blue/DAB vectors
// 02/Nov/2005 changed code to work with image stacks (DLC - dchao at fhcrc org)
// 02/Nov/2005 changed field names so user-defined colours can be set within
// macros (DLC - dchao at fhcrc org)
// 04/Feb/2007 1.3 disable popup menu when right clicking
// 23/May/2009 added Feulgen-light green vectors
//14/Apr/2010 v 1.4 added Giemsa vector (Methylene blue & eosin)
// the images are now names "title"-(Colour_1) etc so there are not clash of names when using [ ]
// the log window now prints the java code of the translation matrix to include new vectors in the plugin.
// added "Hide legend" option
//22/Jun/2010 v 1.5 added Masson Trichrome vector (Methyl blue & Ponceau Fuchsin only (this does not have Iron Haematoxylin vector!)
// fixed bug: check for 0 components before hiding legend (otherwise there was no image shown if legent hidden)
//
// This plugin implements stain separation using the colour deconvolution
// method described in:
//
// Ruifrok AC, Johnston DA. Quantification of histochemical
// staining by color deconvolution. Analytical & Quantitative
// Cytology & Histology 2001; 23: 291-299.
//
// The code is based on "Color separation-30", a macro for NIH Image kindly provided
// by A.C. Ruifrok. Thanks Arnout!
//
// The plugin assumes images generated by color subtraction (i.e. light-absorbing dyes
// such as those used in bright field histology or ink on printed paper) but the dyes
// should not be neutral grey.
//
// I strongly suggest to read the paper reference above to understand how to determine
// new vectors and how the whole procedure works.
//
// The plugin works correctly when the background is neutral (white to light grey),
// so background subtraction and colour correction must be applied to the images before
// processing.
//
// The plugin provides a number of "built in" stain vectors some of which were determined
// experimentally in our lab (marked GL), but you may have to determine your own vectors to
// provide a more accurate stain separation, depending on the stains and methods you use.
// Ideally, vector determination should be done on slides stained with only one colour
// at a time (using the "From ROI" interactive option).
//
// The plugin takes an RGB image and returns three 8-bit images. If the specimen is
// stained with a 2 colour scheme (such as H & E) the 3rd image represents the
// complimentary of the first two colours (i.e. green).
//
// Please be *very* careful about how to interpret the results of colour deconvolution
// when analysing histological images.
// Most staining methods are not stochiometric and so optical density of the chromogen
// may not correlate well with the *quantity* of the reactants.
// This means that optical density of the colour may not be a good indicator of
// the amount of material stained.
//
// Read the paper!
//
public static final String DECONV_NONE = "None";
public static final String[] stainings = {/*"From ROI", */"H&E", "H&E 2", "H DAB", "H DAB FastRed", "Feulgen Light Green", "Giemsa", "FastRed FastBlue DAB", "Methyl Green DAB", "H&E DAB", "H AEC", "Azan-Mallory", "Masson Trichrome", "Alcian blue & H", "H PAS", "RGB", "CMY"/*, "User values"*/};
private final static Colour_Deconvolution deconv = new Colour_Deconvolution();
public void run(String stain) {
ImagePlus imp = WindowManager.getCurrentImage();
ImagePlus[] img = run(imp, stain);
if (img != null && img.length >= 3) {
img[0].show();
img[1].show();
img[2].show();
}
}
public ImagePlus[] run(ImagePlus imp, String myStain) {
//ImagePlus imp = WindowManager.getCurrentImage();
if (imp == null) {
err("No image!");
return null;
}
if (imp.getBitDepth() != 24) {
err("RGB image needed.");
return null;
}
ImageStack stack = imp.getStack();
int width = stack.getWidth();
int height = stack.getHeight();
String title = imp.getTitle();
boolean doIshow = false; // debug messages
double leng, A, V, C, log255 = Math.log(255.0);
int i, j;
double[] MODx = new double[3];
double[] MODy = new double[3];
double[] MODz = new double[3];
double[] cosx = new double[3];
double[] cosy = new double[3];
double[] cosz = new double[3];
double[] len = new double[3];
double[] q = new double[9];
byte[] rLUT = new byte[256];
byte[] gLUT = new byte[256];
byte[] bLUT = new byte[256];
// stains are defined after this line
if (myStain.equals("H&E")) {
// GL Haem matrix
MODx[0] = 0.644211; //0.650;
MODy[0] = 0.716556; //0.704;
MODz[0] = 0.266844; //0.286;
// GL Eos matrix
MODx[1] = 0.092789; //0.072;
MODy[1] = 0.954111; //0.990;
MODz[1] = 0.283111; //0.105;
// Zero matrix
MODx[2] = 0.0;
MODy[2] = 0.0;
MODz[2] = 0.0;
}
if (myStain.equals("H&E 2")) {
// GL Haem matrix
MODx[0] = 0.49015734;
MODy[0] = 0.76897085;
MODz[0] = 0.41040173;
// GL Eos matrix
MODx[1] = 0.04615336;
MODy[1] = 0.8420684;
MODz[1] = 0.5373925;
// Zero matrix
MODx[2] = 0.0;
MODy[2] = 0.0;
MODz[2] = 0.0;
}
if (myStain.equals("H DAB")) {
// 3,3-diamino-benzidine tetrahydrochloride
// Haem matrix
MODx[0] = 0.650;
MODy[0] = 0.704;
MODz[0] = 0.286;
// DAB matrix
MODx[1] = 0.268;
MODy[1] = 0.570;
MODz[1] = 0.776;
// Zero matrix
MODx[2] = 0.0;
MODy[2] = 0.0;
MODz[2] = 0.0;
}
// Manuel: 3.2.2016
if (myStain.equals("H DAB FastRed")) {
// Haem matrix
MODx[0] = 0.650;
MODy[0] = 0.704;
MODz[0] = 0.286;
// DAB matrix
MODx[1] = 0.268;
MODy[1] = 0.570;
MODz[1] = 0.776;
// //fast red
MODx[2] = 0.21393921;
MODy[2] = 0.85112669;
MODz[2] = 0.47794022;
}
if (myStain.equals("Feulgen Light Green")) {
//GL Feulgen & light green
//Feulgen
MODx[0] = 0.46420921;
MODy[0] = 0.83008335;
MODz[0] = 0.30827187;
// light green
MODx[1] = 0.94705542;
MODy[1] = 0.25373821;
MODz[1] = 0.19650764;
// Zero matrix
MODx[2] = 0.0; // 0.0010000
MODy[2] = 0.0; // 0.47027777
MODz[2] = 0.0; //0.88235928
}
if (myStain.equals("Giemsa")) {
// GL Methylene Blue and Eosin
MODx[0] = 0.834750233;
MODy[0] = 0.513556283;
MODz[0] = 0.196330403;
// GL Eos matrix
MODx[1] = 0.092789;
MODy[1] = 0.954111;
MODz[1] = 0.283111;
// Zero matrix
MODx[2] = 0.0;
MODy[2] = 0.0;
MODz[2] = 0.0;
}
if (myStain.equals("FastRed FastBlue DAB")) {
//fast red
MODx[0] = 0.21393921;
MODy[0] = 0.85112669;
MODz[0] = 0.47794022;
// fast blue
MODx[1] = 0.74890292;
MODy[1] = 0.60624161;
MODz[1] = 0.26731082;
// dab
MODx[2] = 0.268;
MODy[2] = 0.570;
MODz[2] = 0.776;
}
if (myStain.equals("Methyl Green DAB")) {
// MG matrix (GL)
MODx[0] = 0.98003;
MODy[0] = 0.144316;
MODz[0] = 0.133146;
// DAB matrix
MODx[1] = 0.268;
MODy[1] = 0.570;
MODz[1] = 0.776;
// Zero matrix
MODx[2] = 0.0;
MODy[2] = 0.0;
MODz[2] = 0.0;
}
if (myStain.equals("H&E DAB")) {
// Haem matrix
MODx[0] = 0.650;
MODy[0] = 0.704;
MODz[0] = 0.286;
// Eos matrix
MODx[1] = 0.072;
MODy[1] = 0.990;
MODz[1] = 0.105;
// DAB matrix
MODx[2] = 0.268;
MODy[2] = 0.570;
MODz[2] = 0.776;
}
if (myStain.equals("H AEC")) {
// 3-amino-9-ethylcarbazole
// Haem matrix
MODx[0] = 0.650;
MODy[0] = 0.704;
MODz[0] = 0.286;
// AEC matrix
MODx[1] = 0.2743;
MODy[1] = 0.6796;
MODz[1] = 0.6803;
// Zero matrix
MODx[2] = 0.0;
MODy[2] = 0.0;
MODz[2] = 0.0;
}
if (myStain.equals("Azan-Mallory")) {
//Azocarmine and Aniline Blue (AZAN)
// GL Blue matrix Anilline Blue
MODx[0] = .853033;
MODy[0] = .508733;
MODz[0] = .112656;
// GL Red matrix Azocarmine
MODx[1] = 0.09289875;
MODy[1] = 0.8662008;
MODz[1] = 0.49098468;
//GL Orange matrix Orange-G
MODx[2] = 0.10732849;
MODy[2] = 0.36765403;
MODz[2] = 0.9237484;
}
if (myStain.equals("Masson Trichrome")) {
// GL Methyl blue
MODx[0] = 0.7995107;
MODy[0] = 0.5913521;
MODz[0] = 0.10528667;
// GL Ponceau Fuchsin has 2 hues, really this is only approximate
MODx[1] = 0.09997159;
MODy[1] = 0.73738605;
MODz[1] = 0.6680326;
// Zero matrix
MODx[2] = 0.0;
MODy[2] = 0.0;
MODz[2] = 0.0;
// GL Iron Haematoxylin, but this does not seem to work well because it gets confused with the other 2 components
// MODx[2]=0.6588232;
// MODy[2]=0.66414213;
// MODz[2]=0.3533655;
}
if (myStain.equals("Alcian blue & H")) {
// GL Alcian Blue matrix
MODx[0] = 0.874622;
MODy[0] = 0.457711;
MODz[0] = 0.158256;
// GL Haematox after PAS matrix
MODx[1] = 0.552556;
MODy[1] = 0.7544;
MODz[1] = 0.353744;
// Zero matrix
MODx[2] = 0.0;
MODy[2] = 0.0;
MODz[2] = 0.0;
}
if (myStain.equals("H PAS")) {
// GL Haem matrix
MODx[0] = 0.644211; //0.650;
MODy[0] = 0.716556; //0.704;
MODz[0] = 0.266844; //0.286;
// GL PAS matrix
MODx[1] = 0.175411;
MODy[1] = 0.972178;
MODz[1] = 0.154589;
// Zero matrix
MODx[2] = 0.0;
MODy[2] = 0.0;
MODz[2] = 0.0;
}
if (myStain.equals("RGB")) {
//R
MODx[0] = 0.0;
MODy[0] = 1.0;
MODz[0] = 1.0;
//G
MODx[1] = 1.0;
MODy[1] = 0.0;
MODz[1] = 1.0;
//B
MODx[2] = 1.0;
MODy[2] = 1.0;
MODz[2] = 0.0;
}
if (myStain.equals("CMY")) {
//C
MODx[0] = 1.0;
MODy[0] = 0.0;
MODz[0] = 0.0;
//M
MODx[1] = 0.0;
MODy[1] = 1.0;
MODz[1] = 0.0;
//Y
MODx[2] = 0.0;
MODy[2] = 0.0;
MODz[2] = 1.0;
}
/*
if (myStain.equals("User values")){
GenericDialog gd2 = new GenericDialog("User values", IJ.getInstance());
gd2.addMessage("Colour[1]");
gd2.addNumericField("[R1]", 0, 5);
gd2.addNumericField("[G1]", 0, 5);
gd2.addNumericField("[B1]", 0, 5);
gd2.addMessage("Colour[2]");
gd2.addNumericField("[R2]", 0, 5);
gd2.addNumericField("[G2]", 0, 5);
gd2.addNumericField("[B2]", 0, 5);
gd2.addMessage("Colour[3]");
gd2.addNumericField("[R3]", 0, 5);
gd2.addNumericField("[G3]", 0, 5);
gd2.addNumericField("[B3]", 0, 5);
gd2.showDialog();
if (gd2.wasCanceled())
return;
MODx[0]= gd2.getNextNumber();
MODy[0]= gd2.getNextNumber();
MODz[0]= gd2.getNextNumber();
MODx[1]= gd2.getNextNumber();
MODy[1]= gd2.getNextNumber();
MODz[1]= gd2.getNextNumber();
MODx[2]= gd2.getNextNumber();
MODy[2]= gd2.getNextNumber();
MODz[2]= gd2.getNextNumber();
}
*/
/*
if (myStain.equals("From ROI")){
IJ.runMacro("setOption('DisablePopupMenu', true)");
// imp.getCanvas().disablePopupMenu(true);
double [] rgbOD = new double[3];
for (i=0; i<3; i++){
getmeanRGBODfromROI(i, rgbOD, imp);
MODx[i]= rgbOD[0];
MODy[i]= rgbOD[1];
MODz[i]= rgbOD[2];
}
IJ.runMacro("setOption('DisablePopupMenu', false)");
// imp.getCanvas().disablePopupMenu(false);
}
*/
// start
for (i = 0; i < 3; i++) {
//normalise vector length
cosx[i] = cosy[i] = cosz[i] = 0.0;
len[i] = Math.sqrt(MODx[i] * MODx[i] + MODy[i] * MODy[i] + MODz[i] * MODz[i]);
if (len[i] != 0.0) {
cosx[i] = MODx[i] / len[i];
cosy[i] = MODy[i] / len[i];
cosz[i] = MODz[i] / len[i];
}
}
// translation matrix
if (cosx[1] == 0.0) { //2nd colour is unspecified
if (cosy[1] == 0.0) {
if (cosz[1] == 0.0) {
cosx[1] = cosz[0];
cosy[1] = cosx[0];
cosz[1] = cosy[0];
}
}
}
if (cosx[2] == 0.0) { // 3rd colour is unspecified
if (cosy[2] == 0.0) {
if (cosz[2] == 0.0) {
if ((cosx[0] * cosx[0] + cosx[1] * cosx[1]) > 1) {
if (doIshow)
iLog("Colour_3 has a negative R component.");
cosx[2] = 0.0;
} else {
cosx[2] = Math.sqrt(1.0 - (cosx[0] * cosx[0]) - (cosx[1] * cosx[1]));
}
if ((cosy[0] * cosy[0] + cosy[1] * cosy[1]) > 1) {
if (doIshow)
iLog("Colour_3 has a negative G component.");
cosy[2] = 0.0;
} else {
cosy[2] = Math.sqrt(1.0 - (cosy[0] * cosy[0]) - (cosy[1] * cosy[1]));
}
if ((cosz[0] * cosz[0] + cosz[1] * cosz[1]) > 1) {
if (doIshow)
iLog("Colour_3 has a negative B component.");
cosz[2] = 0.0;
} else {
cosz[2] = Math.sqrt(1.0 - (cosz[0] * cosz[0]) - (cosz[1] * cosz[1]));
}
}
}
}
leng = Math.sqrt(cosx[2] * cosx[2] + cosy[2] * cosy[2] + cosz[2] * cosz[2]);
cosx[2] = cosx[2] / leng;
cosy[2] = cosy[2] / leng;
cosz[2] = cosz[2] / leng;
for (i = 0; i < 3; i++) {
if (cosx[i] == 0.0) cosx[i] = 0.001;
if (cosy[i] == 0.0) cosy[i] = 0.001;
if (cosz[i] == 0.0) cosz[i] = 0.001;
}
/* if (myStain.equals("From ROI")){
IJ.showMessage("Vectors","Colour[1]:\n"+
" R: "+(float) cosx[0] +"\n"+
" G: "+(float) cosy[0] +"\n"+
" B: "+(float) cosz[0] +"\n \n"+
"Colour[2]:\n"+
" R: "+ (float) cosx[1] +"\n"+
" G: "+ (float) cosy[1] +"\n"+
" B: "+ (float) cosz[1] +"\n \n"+
"Colour[3]:\n"+
" R: "+ (float) cosx[2] +"\n"+
" G: "+ (float) cosy[2] +"\n"+
" B: "+ (float) cosz[2]);
}
*/
if (doIshow) {
iLog(myStain + " Vector Matrix ---");
for (i = 0; i < 3; i++) {
iLog("Colour[" + (i + 1) + "]:\n" +
" R" + (i + 1) + ": " + (float) MODx[i] + "\n" +
" G" + (i + 1) + ": " + (float) MODy[i] + "\n" +
" B" + (i + 1) + ": " + (float) MODz[i] + "\n \n");
}
/* iLog( myStain +" Translation Matrix ---");
for (i=0; i<3; i++){
iLog("Colour["+(i+1)+"]:\n"+
" R"+(i+1)+": "+ (float) cosx[i] +"\n"+
" G"+(i+1)+": "+ (float) cosy[i] +"\n"+
" B"+(i+1)+": "+ (float) cosz[i] +"\n \n");
}
*/
iLog(myStain + " Java code ---");
iLog("\t\tif (myStain.equals(\"New_Stain\")){");
iLog("\t\t// This is the New_Stain");
for (i = 0; i < 3; i++) {
iLog("\t\t\tMODx[" + i + "]=" + (float) cosx[i] + ";\n" +
"\t\t\tMODy[" + i + "]=" + (float) cosy[i] + ";\n" +
"\t\t\tMODz[" + i + "]=" + (float) cosz[i] + ";\n\n");
}
iLog("}");
}
//matrix inversion
A = cosy[1] - cosx[1] * cosy[0] / cosx[0];
V = cosz[1] - cosx[1] * cosz[0] / cosx[0];
C = cosz[2] - cosy[2] * V / A + cosx[2] * (V / A * cosy[0] / cosx[0] - cosz[0] / cosx[0]);
q[2] = (-cosx[2] / cosx[0] - cosx[2] / A * cosx[1] / cosx[0] * cosy[0] / cosx[0] + cosy[2] / A * cosx[1] / cosx[0]) / C;
q[1] = -q[2] * V / A - cosx[1] / (cosx[0] * A);
q[0] = 1.0 / cosx[0] - q[1] * cosy[0] / cosx[0] - q[2] * cosz[0] / cosx[0];
q[5] = (-cosy[2] / A + cosx[2] / A * cosy[0] / cosx[0]) / C;
q[4] = -q[5] * V / A + 1.0 / A;
q[3] = -q[4] * cosy[0] / cosx[0] - q[5] * cosz[0] / cosx[0];
q[8] = 1.0 / C;
q[7] = -q[8] * V / A;
q[6] = -q[7] * cosy[0] / cosx[0] - q[8] * cosz[0] / cosx[0];
// initialize 3 output colour stacks
ImageStack[] outputstack = new ImageStack[3];
for (i = 0; i < 3; i++) {
for (j = 0; j < 256; j++) { //LUT[1]
//if (cosx[i] < 0)
// rLUT[255-j]=(byte)(255.0 + (double)j * cosx[i]);
//else
rLUT[255 - j] = (byte) (255.0 - (double) j * cosx[i]);
//if (cosy[i] < 0)
// gLUT[255-j]=(byte)(255.0 + (double)j * cosy[i]);
//else
gLUT[255 - j] = (byte) (255.0 - (double) j * cosy[i]);
//if (cosz[i] < 0)
// bLUT[255-j]=(byte)(255.0 + (double)j * cosz[i]);
///else
bLUT[255 - j] = (byte) (255.0 - (double) j * cosz[i]);
}
IndexColorModel cm = new IndexColorModel(8, 256, rLUT, gLUT, bLUT);
outputstack[i] = new ImageStack(width, height, cm);
}
// translate ------------------
int imagesize = width * height;
for (int imagenum = 1; imagenum <= stack.getSize(); imagenum++) {
int[] pixels = (int[]) stack.getPixels(imagenum);
String label = stack.getSliceLabel(imagenum);
byte[][] newpixels = new byte[3][];
newpixels[0] = new byte[imagesize];
newpixels[1] = new byte[imagesize];
newpixels[2] = new byte[imagesize];
for (j = 0; j < imagesize; j++) {
// log transform the RGB data
int R = (pixels[j] & 0xff0000) >> 16;
int G = (pixels[j] & 0x00ff00) >> 8;
int B = (pixels[j] & 0x0000ff);
double Rlog = -((255.0 * Math.log(((double) R + 1) / 255.0)) / log255);
double Glog = -((255.0 * Math.log(((double) G + 1) / 255.0)) / log255);
double Blog = -((255.0 * Math.log(((double) B + 1) / 255.0)) / log255);
for (i = 0; i < 3; i++) {
// rescale to match original paper values
double Rscaled = Rlog * q[i * 3];
double Gscaled = Glog * q[i * 3 + 1];
double Bscaled = Blog * q[i * 3 + 2];
double output = Math.exp(-((Rscaled + Gscaled + Bscaled) - 255.0) * log255 / 255.0);
if (output > 255) output = 255;
newpixels[i][j] = (byte) (0xff & (int) (Math.floor(output + .5)));
}
}
// add new values to output images
outputstack[0].addSlice(label, newpixels[0]);
outputstack[1].addSlice(label, newpixels[1]);
outputstack[2].addSlice(label, newpixels[2]);
}
ImagePlus img1 = new ImagePlus(title + "-(Colour_1)", outputstack[0]);
ImagePlus img2 = new ImagePlus(title + "-(Colour_2)", outputstack[1]);
ImagePlus img3 = new ImagePlus(title + "-(Colour_3)", outputstack[2]);
return new ImagePlus[]{img1, img2, img3};
}
/*
void getmeanRGBODfromROI(int i, double [] rgbOD, ImagePlus imp){
//get a ROI and its mean optical density. GL
int [] xyzf = new int [4]; //[0]=x, [1]=y, [2]=z, [3]=flags
int x1, y1, x2, y2, h=0, w=0, px=0, py=0, x, y,p;
double log255=Math.log(255.0);
ImageProcessor ip = imp.getProcessor();
int mw = ip.getWidth()-1;
int mh = ip.getHeight()-1;
IJ.showMessage("Select ROI for Colour_"+(i+1)+".\n \n(Right-click to end)");
getCursorLoc( xyzf, imp );
while ((xyzf[3] & 4) !=0){ //trap until right released
getCursorLoc( xyzf, imp );
IJ.wait(20);
}
while (((xyzf[3] & 16) == 0) && ((xyzf[3] & 4) ==0)) { //trap until one is pressed
getCursorLoc( xyzf, imp );
IJ.wait(20);
}
rgbOD[0]=0;
rgbOD[1]=0;
rgbOD[2]=0;
if ((xyzf[3] & 4) == 0){// right was not pressed, but left (ROI) was
x1=xyzf[0];
y1=xyzf[1];
//IJ.write("first point x:" + x1 + " y:" + y1);
x2=x1; y2=y1;
while ((xyzf[3] & 4) == 0){//until right pressed
getCursorLoc( xyzf, imp );
if (xyzf[0]!=x2 || xyzf[1]!=y2) {
if (xyzf[0]<0) xyzf[0]=0;
if (xyzf[1]<0) xyzf[1]=0;
if (xyzf[0]>mw) xyzf[0]=mw;
if (xyzf[1]>mh) xyzf[1]=mh;
x2=xyzf[0]; y2=xyzf[1];
w=x2-x1+1;
h=y2-y1+1;
if (x2>16)+1)/255.0))/log255));
rgbOD[1] = rgbOD[1]+ (-((255.0*Math.log(((double)((p & 0x00ff00)>> 8) +1)/255.0))/log255));
rgbOD[2] = rgbOD[2]+ (-((255.0*Math.log(((double)((p & 0x0000ff)) +1)/255.0))/log255));
}
}
rgbOD[0] = rgbOD[0] / (w*h);
rgbOD[1] = rgbOD[1] / (w*h);
rgbOD[2] = rgbOD[2] / (w*h);
}
IJ.run("Select None");
}
void getCursorLoc(int [] xyzf, ImagePlus imp ) {
ImageWindow win = imp.getWindow();
ImageCanvas ic = win.getCanvas();
Point p = ic.getCursorLoc();
xyzf[0]=p.x;
xyzf[1]=p.y;
xyzf[2]=imp.getCurrentSlice()-1;
xyzf[3]=ic.getModifiers();
}
*/
private void err(String s) {
System.out.println("error: " + s);
}
private void iLog(String s) {
System.out.println("log: " + s);
}
public static BufferedImage getProcessedImage(BufferedImage source, String stain, int channel, BufferedImage createdImage) {
try {
ImagePlus ip = new ImagePlus("img", source);
ip = deconv.run(ip, stain)[channel];
BufferedImage bi;
if (createdImage != null)
bi = createdImage;
else bi = new BufferedImage(ip.getWidth(), ip.getHeight(), source.getType());
bi.createGraphics().drawImage(ip.getImage(), 0, 0, null);
return bi;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Testmethod
*
* @param args
*/
public static void main(String[] args) throws Exception {
BufferedImage img = ImageIO.read(new File("d:/pic/colorDeconv/hd.png"));
img = deconv.run(new ImagePlus("Image", img), "H DAB")[0].getBufferedImage();
ImagePane ip = new ImagePane(img);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setSize(200, 200);
frame.add(ip);
RawUtilsCommon.centerComponent(frame);
frame.setVisible(true);
}
}