3 TrakEM2 plugin for ImageJ(C).
4 Copyright (C) 2005-2009 Albert Cardona and Rodney Douglas.
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation (http://www.gnu.org/licenses/gpl.txt )
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 You may contact Albert Cardona at acardona at ini.phys.ethz.ch
20 Institute of Neuroinformatics, University of Zurich / ETH, Switzerland.
23 package ini
.trakem2
.display
;
30 import ini
.trakem2
.utils
.Utils
;
31 import ini
.trakem2
.utils
.IJError
;
32 import ini
.trakem2
.imaging
.PatchStack
;
33 import ini
.trakem2
.imaging
.LayerStack
;
35 import java
.awt
.Rectangle
;
36 import java
.util
.ArrayList
;
37 import java
.awt
.image
.ColorModel
;
38 import java
.awt
.geom
.Point2D
;
40 /** Need a non-null ImagePlus for the ImageCanvas, even if fake. */
41 public class FakeImagePlus
extends ImagePlus
{
45 private Display display
;
48 public FakeImagePlus(int width
, int height
, Display display
) {
51 this.display
= display
;
52 setProcessor("", new FakeProcessor(width
, height
));
53 type
= ImagePlus
.GRAY8
;
55 public void setProcessor(String title
, ImageProcessor ip
) {
56 if (! (ip
instanceof FakeProcessor
)) return;
57 super.setProcessor(title
, ip
);
59 public void flush() {} // disabled
60 protected Display
getDisplay() {
63 public int getType() { return type
; }
64 public int getWidth() {
65 // trick the canvas, but not the ROIs
66 //Class dc = null; try { dc = Class.forName("ini.trakem2.DisplayCanvas"); } catch (Exception e) {}
67 if ((Utils
.caller(this)).endsWith("ImageCanvas")) return 4;
70 public int getHeight() {
71 // trick the canvas, but not the ROIs
72 //Class dc = null; try { dc = Class.forName("ini.trakem2.DisplayCanvas"); } catch (Exception e) {}
73 if ((Utils
.caller(this)).endsWith("ImageCanvas")) return 4;
77 /** Used to resize the canvas. */
78 public void setDimensions(int width
, int height
) {
83 public int[] getPixel(int x
, int y
) {
85 //return display.getLayer().getPixel(x, y, display.getCanvas().getMagnification());
86 return ((FakeProcessor
)getProcessor()).getPixel(display
.getCanvas().getMagnification(), x
, y
, null);
87 } catch (Exception e
) {
93 private class FakeProcessor
extends ByteProcessor
{
94 FakeProcessor(int width
, int height
) {
95 // create a 4x4 processor (just because, perhaps to skip nulls)
98 /** Override to return the pixel of the Patch under x,y, if any. */
99 public int getPixel(final int x
, final int y
) {
100 return getPixel(1.0, x
, y
);
102 public int getPixel(double mag
, final int x
, final int y
) {
103 if (mag
> 1) mag
= 1;
104 final ArrayList al
= display
.getLayer().getDisplayables();
105 final Displayable
[] d
= new Displayable
[al
.size()];
107 int pixel
= 0; // will return black if nothing found
108 // reverse lookup, for the top ones are at the bottom of the array
109 for (int i
=d
.length
-1; i
>-1; i
--) {
110 if (d
[i
].getClass() == Patch
.class && d
[i
].contains(x
, y
)) {
111 Patch p
= (Patch
)d
[i
];
112 FakeImagePlus
.this.type
= p
.getType(); // for proper value string display
113 return p
.getPixel(mag
, x
, y
);
118 public int[] getPixel(int x
, int y
, int[] iArray
) {
119 return getPixel(1.0, x
, y
, iArray
);
121 public int[] getPixel(double mag
, int x
, int y
, int[] iArray
) {
122 if (mag
> 1) mag
= 1;
123 ArrayList al
= display
.getLayer().getDisplayables();
124 final Displayable
[] d
= new Displayable
[al
.size()];
126 // reverse lookup, for the top ones are at the bottom of the array
127 for (int i
=d
.length
-1; i
>-1; i
--) {
128 if (d
[i
].getClass() == Patch
.class && d
[i
].contains(x
, y
)) {
129 Patch p
= (Patch
)d
[i
];
130 FakeImagePlus
.this.type
= p
.getType(); // for proper value string display
131 if (!p
.isStack() && Math
.max(p
.getWidth(), p
.getHeight()) * mag
>= 1024) {
132 // Gather the ImagePlus: will be faster than using a PixelGrabber on an awt image
133 Point2D
.Double po
= p
.inverseTransformPoint(x
, y
);
134 ImageProcessor ip
= p
.getImageProcessor();
135 if (null != ip
) return ip
.getPixel((int)po
.x
, (int)po
.y
, iArray
);
137 return p
.getPixel(mag
, x
, y
, iArray
);
140 return null == iArray ?
new int[4] : iArray
;
142 public int getWidth() { return w
; }
143 public int getHeight() { return h
; }
145 public void setColorModel(ColorModel cm
) {
146 display
.getSelection().setLut(cm
);
149 public void setPixels(Object ob
) {} // disabled
152 // TODO: use layerset virtualization
153 public ImageStatistics
getStatistics(int mOptions
, int nBins
, double histMin
, double histMax
) {
154 Displayable active
= display
.getActive();
155 if (null == active
|| !(active
instanceof Patch
)) {
156 Utils
.log("No patch selected.");
157 return super.getStatistics(mOptions
, nBins
, histMin
, histMax
); // TODO can't return null, but something should be done about it.
159 ImagePlus imp
= active
.getProject().getLoader().fetchImagePlus((Patch
)active
);
160 ImageProcessor ip
= imp
.getProcessor(); // don't create a new onw every time // ((Patch)active).getProcessor();
161 Roi roi
= super.getRoi();
163 // translate ROI to be meaningful for the Patch
164 int patch_x
= (int)active
.getX();
165 int patch_y
= (int)active
.getY();
166 Rectangle r
= roi
.getBounds();
167 roi
.setLocation(patch_x
- r
.x
, patch_y
- r
.y
);
169 ip
.setRoi(roi
); // even if null, to reset
170 ip
.setHistogramSize(nBins
);
171 Calibration cal
= getCalibration();
172 if (getType()==GRAY16
&& !(histMin
==0.0&&histMax
==0.0))
173 {histMin
=cal
.getRawValue(histMin
); histMax
=cal
.getRawValue(histMax
);}
174 ip
.setHistogramRange(histMin
, histMax
);
175 ImageStatistics stats
= ImageStatistics
.getStatistics(ip
, mOptions
, cal
);
176 ip
.setHistogramSize(256);
177 ip
.setHistogramRange(0.0, 0.0);
181 /** Returns a virtual stack made of boxes with the dimension of the ROI or the whole layer, so that pixels are retrieved on the fly. */
182 public ImageStack
getStack() {
187 public int getStackCount() {
189 //return display.getLayer().getParent().size();
192 public boolean isVirtual() { return true; }
194 /** Returns the super, which is a dummy 4x4 */ //Returns a virtual stack made of boxes with the dimension of the ROI or the whole layer, so that pixels are retrieved on the fly.
195 public ImageProcessor
getProcessor() {
196 return super.getProcessor();
199 /** Forward to LayerSet. */
200 public void setCalibration(Calibration cal
) {
201 try { super.setCalibration(cal
); } catch (Throwable e
) { IJError
.print(e
); }
202 display
.getLayer().getParent().setCalibration(cal
);
205 public void setCalibrationSuper(Calibration cal
) {
206 super.setCalibration(cal
);
209 public Calibration
getCalibration() {
210 // initialization problems with ij1.40a
211 if (null == display
|| null == display
.getLayer()) return new Calibration();
212 return display
.getLayer().getParent().getCalibrationCopy();
215 /** Forward kill roi to the last_temp of the associated Display. */
216 public void killRoi() {
220 ImageProcessor ip
= getProcessor();
221 if (null != ip
) ip
.resetRoi();
225 public synchronized void setSlice(int slice
) {}
227 public void updateAndRepaintWindow() {
228 // TODO: if a selected image is a stack, the LUT applies to it as well...
229 Display
.repaint(display
.getLayer(), display
.getSelection().getBox(), 0);