Commit b6a7bf3f authored by lafabregue's avatar lafabregue

finished pyramid iamge implementation

parent 0f66b211
......@@ -123,7 +123,7 @@ public class MainFrame extends JFrame {
private JPanel infosPanel;
/** boolean pour lier le birdview avec l'image active */
private boolean lierBirdView = false;
private boolean linkToAllImages = false;
/** the project root for datas */
private DefaultMutableTreeNode mDataProjectNode;
......@@ -1310,8 +1310,8 @@ public class MainFrame extends JFrame {
menuBrightM.setEnabled(this.actionBrightM);
menuContrastP.setEnabled(this.actionContratsP);
menuContrastM.setEnabled(this.actionContrastM);
menuConnectActiv.setEnabled(!this.isLierBirdView());
menuConnectAll.setEnabled(this.isLierBirdView());
menuConnectActiv.setEnabled(!this.isLinkToAllBirdView());
menuConnectAll.setEnabled(this.isLinkToAllBirdView());
menuResetAll.setEnabled(this.actionResetAll);
menuChooseRgb.setEnabled(this.actionChooseRgb);
menuRefresh.setEnabled(this.actionRefresh);
......@@ -1480,7 +1480,7 @@ public class MainFrame extends JFrame {
// =============== Creation of the Desktop ================
JPanel panel_desktop = new JPanel(new BorderLayout());
panel_desktop.setOpaque(false);
panel_desktop.setBorder(Borders.DIALOG);
panel_desktop.setBorder(Borders.DIALOG_BORDER);
panel_desktop.add(this.desktop);
sif_desktop = new SimpleInternalFrame(Messages.getString("MainFrame.72")); //$NON-NLS-1$
......@@ -1494,7 +1494,7 @@ public class MainFrame extends JFrame {
JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(false);
panel.setBorder(Borders.DIALOG);
panel.setBorder(Borders.DIALOG_BORDER);
panel.add(pane);
// =============== Creation of the Progress Panel => South
......@@ -1530,36 +1530,6 @@ public class MainFrame extends JFrame {
this.birdPanel.requestFocus();
}
//TODO to remove
// method for resizing an image while keeping aspect ratio
private static BufferedImage resizeImage(BufferedImage originalImage, int type, int frameWidth, int frameHeight) {
double height = originalImage.getHeight();
double width = originalImage.getWidth();
int newWidth, newHeight;
// if image size smaller than window size, do not resize
if (height < frameHeight && width < frameWidth) {
newWidth = (int) width;
newHeight = (int) height;
}
// else resize
else {
double scaleX = (frameWidth / width);
double scaleY = (frameHeight / height);
double scale = Math.min(scaleX, scaleY);
newWidth = (int) (width * scale);
newHeight = (int) (height * scale);
}
BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
g.dispose();
return resizedImage;
}
// 20120309_MBH-Test-Fin
/**
......@@ -1647,7 +1617,7 @@ public class MainFrame extends JFrame {
// =============== Creation of the Desktop ================
JPanel panel_desktop = new JPanel(new BorderLayout());
panel_desktop.setOpaque(false);
panel_desktop.setBorder(Borders.DIALOG);
panel_desktop.setBorder(Borders.DIALOG_BORDER);
panel_desktop.add(this.desktop);
sif_desktop = new SimpleInternalFrame(Messages.getString("MainFrame.72")); //$NON-NLS-1$
......@@ -1661,7 +1631,7 @@ public class MainFrame extends JFrame {
JPanel panel = new JPanel(new BorderLayout());
panel.setOpaque(false);
panel.setBorder(Borders.DIALOG);
panel.setBorder(Borders.DIALOG_BORDER);
panel.add(pane);
// =============== Creation of the Progress Panel => South
......@@ -2494,8 +2464,8 @@ public class MainFrame extends JFrame {
return mDataTreeModel;
}
public boolean isLierBirdView() {
return lierBirdView;
public boolean isLinkToAllBirdView() {
return linkToAllImages;
}
/**
......@@ -3461,7 +3431,7 @@ public class MainFrame extends JFrame {
}
public void setLierBirdView(boolean lierBirdView) {
this.lierBirdView = lierBirdView;
this.linkToAllImages = lierBirdView;
setEnabledMenu();
}
//
......
......@@ -288,29 +288,7 @@ public class BirdViewPanel extends JPanel implements MouseListener,
@Override
public void mouseClicked(MouseEvent e) {
// Test if an image is loaded
if (!session.isDisplayEnable() || this.mImage == null) {
return;
}
// Test if the mouse is over the image
if (e.getPoint().x >= this.mBirdImage.getWidth()
|| e.getPoint().y >= this.mBirdImage.getHeight()) {
return;
}
// Zoom factor of the image
double xfact = (double) this.mImage.getWidth()
/ (double) this.mBirdImage.getWidth();
double yfact = (double) this.mImage.getHeight()
/ (double) this.mBirdImage.getHeight();
double x = e.getX() * xfact;
double y = e.getY() * yfact;
this.mInfoPanel.setPixel((int) (x), (int) (y));
repaint();
}
/**
......@@ -631,7 +609,7 @@ public class BirdViewPanel extends JPanel implements MouseListener,
this.repaint();
this.action = BirdViewPanel.ACT_NONE;
if (!MainFrame.getInstance().isLierBirdView()) {
if (!MainFrame.getInstance().isLinkToAllBirdView()) {
ImageDesktopFrame[] desktopFrames = MainFrame.getInstance().getDesktop()
.getAllImageDesktopFrames();
int nbSessions = desktopFrames.length;
......@@ -653,28 +631,13 @@ public class BirdViewPanel extends JPanel implements MouseListener,
.getBirdViewPanel().rysave);
}
} else {
if (MainFrame.getInstance().getDesktop().getActiveFrame() instanceof ImageDesktopFrame) {
syncImage(((ImageDesktopFrame) MainFrame.getInstance().getDesktop().getActiveFrame())
.getImageSession());
((ImageDesktopFrame) MainFrame
.getInstance()
.getDesktop()
.getActiveFrame())
.getImageSession()
.getImagePanel()
.reloadPoint(
((ImageDesktopFrame) MainFrame.getInstance().getDesktop()
.getActiveFrame()).getImageSession()
.getBirdViewPanel().xxsave,
((ImageDesktopFrame) MainFrame.getInstance().getDesktop()
.getActiveFrame()).getImageSession()
.getBirdViewPanel().yysave,
((ImageDesktopFrame) MainFrame.getInstance().getDesktop()
.getActiveFrame()).getImageSession()
.getBirdViewPanel().rxsave,
((ImageDesktopFrame) MainFrame.getInstance().getDesktop()
.getActiveFrame()).getImageSession()
.getBirdViewPanel().rysave);
if (session != null) {
syncImage(session);
session.getImagePanel().reloadPoint(
session.getBirdViewPanel().xxsave,
session.getBirdViewPanel().yysave,
session.getBirdViewPanel().rxsave,
session.getBirdViewPanel().rysave);
}
}
......
......@@ -406,11 +406,13 @@ public class ImageInformationPanel extends JPanel {
* </p>
*
* @param x
* the x position of the pixel
* the x position of the pixel
* @param y
* the y position of the pixel
* the y position of the pixel
* @param value
* the pixel value
*/
public void setPixel(int x, int y) {
public void setPixel(int x, int y, double value[]) {
this.mPixel.setText("Pixel: " + (x + 1) + " - " + (y + 1));
try {
double posGeo[] = this.mImage.getLatLon(x, y);
......@@ -425,19 +427,12 @@ public class ImageInformationPanel extends JPanel {
this.mPixelGeo.setText("Lat: " + myFormatter.format(xgeo)
+ " Lon: " + myFormatter.format(ygeo));
} catch (Exception ex) {
if(MainFrame.DEBUG_MODE)
ex.printStackTrace();
// if(MainFrame.DEBUG_MODE)
// ex.printStackTrace();
this.mPixelGeo.setText("no georeferencing");
}
double data[][][] = this.mImage.load(x, y, 1, 1);
double realdata[] = new double[data.length];
for (int i = 0; i < data.length; i++)
realdata[i] = data[i][0][0];
setPixelVal(this.mImage.getWavelength(), realdata);
setPixelVal(this.mImage.getWavelength(), value);
}
/**
......
This diff is collapsed.
......@@ -19,11 +19,8 @@ import jcl.Classification;
import jcl.clustering.Cluster;
import jcl.clustering.ClusteringResult;
import jcl.data.Data;
import jcl.data.DataObject;
import jcl.data.SimpleData;
import jcl.data.attribute.AttributeMultiDimSequence;
import jcl.data.attribute.AttributeNumerical;
import jcl.data.mask.Mask;
import jcl.evaluation.clustering.ResultsComparison;
import jcl.learning.*;
import jcl.learning.methods.monostrategy.SingleClassification;
......@@ -643,7 +640,7 @@ public class ImageResultPanel extends ResultPanel implements TreeSelectionListen
}
MainFrame.getInstance().getCurrentDataSession().addResultPanel(this);
this.result = classification.getClusteringResult();
//TODO remove comments to allow display again
//TODO comment line bellow to disable display
this.colored = new BufferedImage(imgData.getResultWidth(), imgData.getResultHeight(), BufferedImage.TYPE_INT_RGB);
if (imgData.getAssociatedImageSessions() != null && imgData.getAssociatedImageSessions().size() > 0) {
this.setData(imgData.getAssociatedImageSessions().get(0).getImagePanel().getImage());
......
......@@ -20,6 +20,7 @@ import com.l2fprod.common.propertysheet.Property;
import jcl.data.mask.Mask;
import jcl.utils.MemoryFlush;
import jcl.utils.Images.StreamedImageReaderWrapper;
import jcl.utils.exceptions.MethodNotImplementedException;
/**
......@@ -129,33 +130,39 @@ public class RawImage implements Serializable, MemoryFlush
* Represents the maximum possible value in the image format
* </p>
*/
private double maxValue = 0;
private double maxValue = 0;
/** min values for each channels */
protected double[] minValues = null;
/** max values for each channels */
protected double[] maxValues = null;
/**
* <p>
* Represents number of bands in the image.
* </p>
*/
private int nbBands = 0;
private int nbBands = 0;
/**
* <p>
* Represents the maximum representative number of bit in the image
* </p>
*/
private short nBitPerPixel = 0;
private short nBitPerPixel = 0;
/**
* Proprietes de l'image
*/
public Vector<Property> properties = new Vector<Property>();
public Vector<Property> properties = new Vector<Property>();
/**
* <p>
* Represents the resolution (in meters/pixel) of the image (0 = X, 1 = Y).
* </p>
*/
private double[] resolution = null;
private double[] resolution = null;
/**
* <p>
......@@ -1192,7 +1199,7 @@ public class RawImage implements Serializable, MemoryFlush
*/
private double[][][] load(ImageReadParam param)
{
System.out.println(">>>>>>>>>>>>>>>>>>> IN ><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
int x;
int y;
int w;
......@@ -2095,6 +2102,64 @@ public class RawImage implements Serializable, MemoryFlush
{
this.workfilename = workfilename;
}
/**
* Return the minimum value for each channel
* @return the minimums
*/
public double[] getMinValues() {
if(minValues == null) {
computeMinMax();
}
return minValues;
}
/**
* Set the minimum value for each channel
* @param minValues
* the minimums
*/
public void setMinValues(double[] minValues) {
this.minValues = minValues;
}
/**
* Return the maximum value for each channel
* @return the maximums
*/
public double[] getMaxValues() {
if(maxValues == null) {
computeMinMax();
}
return maxValues;
}
/**
* Set the maximum value for each channel
* @param maxValues
* the maximums
*/
public void setMaxValues(double[] maxValues) {
this.maxValues = maxValues;
}
/**
* Compute teh min/max values per channel
*/
private void computeMinMax() {
StreamedImageReaderWrapper reader = new StreamedImageReaderWrapper(filename);
long allocatedMemory = (Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory());
long presumableFreeMemory = Runtime.getRuntime().maxMemory() - allocatedMemory;
// we just tack the 2/3rd of the memory available;
presumableFreeMemory *= 0.05;
try {
reader.setMaxRAM(presumableFreeMemory);
} catch (IOException e) {
e.printStackTrace();
}
minValues = reader.getMinValues();
maxValues = reader.getMaxValues();
}
@Override
public void flushMemory() throws MethodNotImplementedException
......
......@@ -178,13 +178,13 @@ public class BufferedImageHelper {
for(int x = 0 ; x < imageWidth ; x++) {
double[] pixel = null;
try {
// try {
pixel = reader.getPixel(x+imageX, y+imageY);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(x+","+y+" in : "+imageX+","+imageY+" - "+imageWidth+","+imageHeight);
e.printStackTrace();
}
// } catch (ArrayIndexOutOfBoundsException e) {
// System.out.println(x+","+y+" in : "+imageX+","+imageY+" - "+imageWidth+","+imageHeight);
// e.printStackTrace();
//
// }
int rgb = 0;
if (maxValues != null && minValues != null) {
rgb = new Color(rescaleColor(pixel[r], 0, maxValues[r]),
......@@ -201,6 +201,16 @@ public class BufferedImageHelper {
return result;
}
/**
* Rescale a value from a given range to 0-255
* @param value
* the value to recale
* @param min
* the min value of the range
* @param max
* the max value of the range
* @return the rescaled value
*/
private static int rescaleColor(double value, double min, double max) {
if (value < min) {
value = min;
......@@ -209,4 +219,51 @@ public class BufferedImageHelper {
}
return (int) ((255 * (value - min)) / (max - min));
}
/**
* Clone a bufferedImage.
* @param bi
* the bufferedImage to copy
* @return the copy of the bufferedImage
*/
public static BufferedImage deepCopy(BufferedImage bi) {
if (bi == null)
return null;
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(bi.getRaster().createCompatibleWritableRaster());
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
/**
* Compute the average image from two images
* For each pixel it's channels values is the average of
* the channel value of the two images.
* The two image have to have the same dimensions
* @param image1
* the first image
* @param image2
* the second image
* @return the average of image1 and image2
*/
public static BufferedImage averagedBufferedImage(BufferedImage image1, BufferedImage image2) {
if (image1.getHeight() != image2.getHeight() ||
image1.getWidth() != image2.getWidth()) {
throw new IndexOutOfBoundsException("the BufferedImage shouyld have the same dimensions");
}
BufferedImage result = new BufferedImage(image1.getWidth(), image1.getHeight(),
BufferedImage.TYPE_INT_RGB);
for(int x = 0 ; x < image1.getWidth() ; x++) {
for(int y = 0 ; y < image1.getHeight() ; y++) {
Color c1 = new Color(image1.getRGB(x, y));
Color c2 = new Color(image2.getRGB(x, y));
Color c = new Color((c1.getRed()+c2.getRed())/2,
(c1.getGreen()+c2.getGreen())/2,
(c1.getBlue()+c2.getBlue())/2);
result.setRGB(x, y, c.getRGB());
}
}
return result;
}
}
......@@ -49,6 +49,8 @@ public class BufferedImageViewer extends ImageViewer {
* - not used if instantiate directly with a BufferedImage */
private short[][][] raster = null;
BufferedImageViewer comparedImage = null;
/**
* Construct a viewer from a raw BufferedImage.
......@@ -190,6 +192,10 @@ public class BufferedImageViewer extends ImageViewer {
+ mask.getOverallCarinality() + " != "
+ (this.getRealImageWidth() + "x" + this.getRealImageHeight()) + ")");
}
if (comparedImage != null) {
comparedImage.addMask(mask);
}
}
private void applyMask() {
......@@ -211,16 +217,15 @@ public class BufferedImageViewer extends ImageViewer {
rgbBands[1] = 1;
rgbBands[2] = 2;
rescale = null;
comparedImage = null;
}
@Override
public BufferedImage getScreenImage(int x, int y, int width, int height, double zoomRate) {
public BufferedImage getScreenImage(int x, int y, int width, int height, double zoomRate, boolean saved) {
if(width <= 0 || height <= 0) {
return null;
}
realX = x;
realY = y;
// we reverse compute the coordinates in the original image
int updatedWidth = (int) Math.ceil(width / zoomRate);
int updatedHeight = (int) Math.ceil(height / zoomRate);
......@@ -232,11 +237,11 @@ public class BufferedImageViewer extends ImageViewer {
if (updatedHeight + y > mSourceImage.getHeight()) {
updatedHeight = mSourceImage.getHeight() - y;
}
mScreenImage = mSourceImage.getSubimage(x, y, updatedWidth, updatedHeight);
BufferedImage screen = mSourceImage.getSubimage(x, y, updatedWidth, updatedHeight);
// we apply the rescale operation
if (rescale != null) {
mScreenImage = this.rescale.filter(mScreenImage, null);
screen = this.rescale.filter(screen, null);
}
// we apply the mask to image
if (mask != null) {
......@@ -245,14 +250,30 @@ public class BufferedImageViewer extends ImageViewer {
// we update the source image to crop to the screen size
AffineTransform trans = AffineTransform.getScaleInstance(zoomRate, zoomRate);
AffineTransformOp op = new AffineTransformOp(trans, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
mScreenImage = op.filter(this.mScreenImage, null);
screen = op.filter(screen, null);
//mScreenImage = op.filter(this.mScreenImage, null).getSubimage(0, 0, width, height);
return mScreenImage;
if (saved) {
realX = x;
realY = y;
mScreenImage = screen;
}
if (comparedImage != null) {
BufferedImage scr2 = comparedImage.getScreenImage(x, y, width, height, zoomRate, saved);
return BufferedImageHelper.averagedBufferedImage(screen, scr2);
}
return screen;
}
@Override
public BufferedImage getScreenImage() {
if (comparedImage != null) {
BufferedImage scr2 = comparedImage.getScreenImage();
return BufferedImageHelper.averagedBufferedImage(mScreenImage, scr2);
}
return mScreenImage;
}
......@@ -274,7 +295,31 @@ public class BufferedImageViewer extends ImageViewer {
this.rescale = new RescaleOp(this.getContrastValue(), this.getBrightnessValue(), null);
this.mScreenImage = this.rescale.filter(this.mScreenImage, null);
}
@Override
public double[] getPixelValue(int x, int y) {
StreamedImageReaderWrapper reader = new StreamedImageReaderWrapper(imagePath);
reader.setBoundries(x, y, x, y);
try {
return reader.getPixel(x, y);
} catch (FormatException | IOException e) {
e.printStackTrace();
}
return null;
}
// TODO this not support images with different dimensions, it should be based on georeferences
@Override
public void addComparedImage(RawImage image) {
if (image == null) {
comparedImage = null;
} else {
comparedImage = new BufferedImageViewer(image, true);
}
}
}
......@@ -3,6 +3,7 @@ package mustic.utils.image;
import java.awt.image.BufferedImage;
import jcl.data.mask.Mask;
import mustic.io.RawImage;
/**
* Abstract class that manage the read operations as BufferedImage
......@@ -31,6 +32,12 @@ public abstract class ImageViewer {
/** max values for each channels */
protected double[] maxValues = null;
/** transparency of the image */
protected float transparency = 1;
/** transparency of the compared image */
protected float comparedImageTransparency = 0.5f;
/**
* Decrease the brightness of the image.
*/
......@@ -171,6 +178,9 @@ public abstract class ImageViewer {
this.maxValues = maxValues;
}
public void adjustTransparency(float firstImage, float secondImage) {
}
/**
* Rescale the image to take in account the modification of the parameters
*
......@@ -209,10 +219,13 @@ public abstract class ImageViewer {
* the height of the output BufferedImage
* @param zoomRate
* the zoomRate between the screen and the originImage
* @param saved
* specify if the parameters should replace the ones currently saved
* this is used to not interfere with getScreenImage() calls
*
* @return the BufferedImage, null the dimension are not valid
*/
public abstract BufferedImage getScreenImage(int x, int y, int width, int height, double zoomRate);
public abstract BufferedImage getScreenImage(int x, int y, int width, int height, double zoomRate, boolean saved);
/**
* Request for the BufferedImage representation of an area in the origin image
......@@ -234,4 +247,18 @@ public abstract class ImageViewer {
* @return the height
*/
public abstract int getRealImageHeight();
/**
* Return the value of a specific pixel
*
* @param x
* x coordinate of the pixel
* @param y
* y coordinate of the pixel
* @return the pixel values per channel
*/
public abstract double[] getPixelValue(int x, int y);
public abstract void addComparedImage(RawImage image);
}
......@@ -8,9 +8,6 @@ import java.io.File;
import java.io.IOException;
import java.util.Vector;
import org.geotools.coverage.grid.ImageGeometry;
import org.hibernate.lob.ReaderInputStream;
import jcl.data.mask.Mask;
import jcl.utils.Images.StreamedImageReaderWrapper;
import loci.formats.FormatException;
......@@ -42,6 +39,12 @@ public class PyramidImageViewer extends ImageViewer {
/** the index of each bands, by default it is the first 3 channels of the image */
private int[] rgbChannels = {0,1,2};
/** min values for each channels */
protected double[] minValues = null;
/** max values for each channels */
protected double[] maxValues = null;
/** the factor of reduction between each layer */
private float pyramidFactor = 2;
......@@ -57,8 +60,8 @@ public class PyramidImageViewer extends ImageViewer {
/** the mask applied to the displayed screen */
private Mask mask = null;
/** the file path of the original source image file */
private String imagePath = null;
/** the RawImage of the original source image file */
private RawImage rawImage = null;
/** file paths of pyramid images */
private Vector<String> pyramidImagesPath = null;
......@@ -66,10 +69,11 @@ public class PyramidImageViewer extends ImageViewer {
/** readers assocaited to pyramid images */
private Vector<StreamedImageReaderWrapper> pyramidReaders = null;
PyramidImageViewer comparedImage = null;
/**
* Construct a viewer from a RawImage.
* Note that it just uses the RawImage to get the filePath.
* The doRescale option should always be set to true, unless you are
* completely sure that the image is already scaled for RGB.
*
......@@ -80,19 +84,7 @@ public class PyramidImageViewer extends ImageViewer {
* false to not change the data
*/
public PyramidImageViewer(RawImage image, boolean doRescale) {
this(image.getFilename(), doRescale);
}
/**
* Construct a viewer from an image file path.
* The doRescale option should always be set to true, unless you are
* completely sure that the image is already scaled for RGB.
*
* @param imagepath
* the path of the image file to allow display to
*/
public PyramidImageViewer(String imagePath, boolean doRescale) {
this.imagePath = imagePath;
this.rawImage = image;
try {
loadImage(doRescale);
} catch (IOException e) {
......@@ -100,7 +92,7 @@ public class PyramidImageViewer extends ImageViewer {
}
init();
}
/**
* Load the image from a file path into the raster and the mScreenImage.