/*
* Copyright (C) 2012 Dr. John Lindsay <jlindsay@uoguelph.ca>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package whiteboxgis;
import java.awt.*;
//import java.awt.geom.*;
import java.awt.image.*;
import javax.swing.*;
import java.io.*;
import java.nio.*;
import java.nio.channels.FileChannel;
/**
*
* @author Dr. John Lindsay email: jlindsay@uoguelph.ca
*/
public class PaletteImage extends JPanel {
public final static int VERTICAL_ORIENTATION = 0;
public final static int HORIZONTAL_ORIENTATION = 1;
private int[] reversePaletteData = null;
private int[] paletteData = null;
private int numPaletteEntries = 0;
private boolean isReversed = false;
private int orientation = VERTICAL_ORIENTATION;
private String paletteFile;
public PaletteImage() {
}
/**
*
* @param width
* @param height
* @param paletteFile
* @param isReversed
* @param orientation
*/
public PaletteImage(int width, int height, String paletteFile, boolean isReversed, int orientation) {
this.setMaximumSize(new Dimension(width, height));
this.setPreferredSize(new Dimension(width, height));
this.paletteFile = paletteFile;
if (!paletteFile.contains("rgb.pal")) {
readPalette();
} else {
numPaletteEntries = 256;
paletteData = new int[numPaletteEntries];
}
reversePaletteData = new int[paletteData.length];
for (int i = 0; i < paletteData.length; i++) {
reversePaletteData[i] = paletteData[paletteData.length - 1 - i];
}
this.isReversed = isReversed;
if (orientation > 1 || orientation < 0) { orientation = 0; }
this.orientation = orientation;
}
public void initialize(int width, int height, String paletteFile, boolean isReversed, int orientation) {
this.setMaximumSize(new Dimension(width, height));
this.setPreferredSize(new Dimension(width, height));
this.paletteFile = paletteFile;
if (!paletteFile.contains("rgb.pal")) {
readPalette();
} else {
numPaletteEntries = 256;
paletteData = new int[numPaletteEntries];
}
reversePaletteData = new int[paletteData.length];
for (int i = 0; i < paletteData.length; i++) {
reversePaletteData[i] = paletteData[paletteData.length - 1 - i];
}
this.isReversed = isReversed;
if (orientation > 1 || orientation < 0) { orientation = 0; }
this.orientation = orientation;
}
public String getPaletteFile() {
return paletteFile;
}
public void setPaletteIsReversed(boolean value) {
this.isReversed = value;
this.repaint();
}
private double gamma = 1.0;
public double getNonlinearity() {
return gamma;
}
public void setNonlinearity(double value) {
gamma = value;
this.repaint();
}
private boolean categorical = false;
private double minValue = 0;
private double maxValue = 0;
public void isCategorical(boolean value, double minValue, double maxValue) {
categorical = value;
if (categorical) {
this.minValue = minValue;
this.maxValue = maxValue;
} else {
this.minValue = -1;
this.maxValue = -1;
}
//(int) (value - minValue) % numPaletteEntries;
}
public boolean isSelected = false;
public Image getPaletteImage() {
try {
int width = getWidth();
int height = getHeight();
Image image = null;
int numDisplayedPaletteEntries = 0;
if (!categorical) {
numDisplayedPaletteEntries = paletteData.length;
} else {
numDisplayedPaletteEntries = (int) (
Math.floor((maxValue - minValue + 1) / numPaletteEntries) + (maxValue - minValue + 1) % numPaletteEntries);
}
int[] imageData = new int[numDisplayedPaletteEntries];
int i, j;
int numPaletteEntriesLessOne = numPaletteEntries - 1;
if (!isReversed && orientation == VERTICAL_ORIENTATION) {
if (!categorical) {
for (i = 0; i < numPaletteEntries; i++) {
j = (int) ((Math.pow((1 - ((double) (i) / numPaletteEntriesLessOne)), gamma)) * numPaletteEntriesLessOne);
imageData[i] = paletteData[j];
}
} else { // it is categorical
for (i = 0; i < numDisplayedPaletteEntries; i++) {
j = (int) (i % numPaletteEntries);
imageData[numDisplayedPaletteEntries - 1 - i] = paletteData[j];
}
}
image = createImage(new MemoryImageSource(1, numDisplayedPaletteEntries, imageData, 0, 1));
} else if (!isReversed && orientation == HORIZONTAL_ORIENTATION) {
for (i = 0; i < numPaletteEntries; i++) {
j = (int)((Math.pow(((double)(i) / numPaletteEntriesLessOne), gamma)) * numPaletteEntriesLessOne);
imageData[i] = paletteData[j];
}
image = createImage(new MemoryImageSource(numPaletteEntries, 1, imageData, 0, 1));
} else if (isReversed && orientation == VERTICAL_ORIENTATION) {
if (!categorical) {
for (i = 0; i < numPaletteEntries; i++) {
j = (int) ((Math.pow(((double) (i) / numPaletteEntriesLessOne), gamma)) * numPaletteEntriesLessOne);
imageData[i] = paletteData[j];
}
} else { // it is categorical
for (i = 0; i < numDisplayedPaletteEntries; i++) {
j = (int) (numPaletteEntries - i % numPaletteEntries - 1);
imageData[numDisplayedPaletteEntries - 1 - i] = paletteData[j];
}
}
image = createImage(new MemoryImageSource(1, numDisplayedPaletteEntries, imageData, 0, 1));
} else if (isReversed && orientation == HORIZONTAL_ORIENTATION) {
for (i = 0; i < numPaletteEntries; i++) {
j = (int)((Math.pow((1 - ((double)(i) / numPaletteEntriesLessOne)), gamma)) * numPaletteEntriesLessOne);
imageData[i] = paletteData[j];
}
image = createImage(new MemoryImageSource(imageData.length, 1, imageData, 0, 1));
}
return image;
} catch (Exception e) {
return null;
}
}
@Override
public void paint (Graphics g) {
try {
Graphics2D g2d = (Graphics2D)g;
if (numPaletteEntries > 50) {
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
}
if (paletteFile != null && (paletteFile.toLowerCase().contains("qual") || paletteFile.toLowerCase().contains("categorical"))) {
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
}
int width = getWidth();
int height = getHeight();
Image image = null;
int numDisplayedPaletteEntries = 0;
if (!categorical) {
numDisplayedPaletteEntries = paletteData.length;
} else {
numDisplayedPaletteEntries = (int) (
Math.floor((maxValue - minValue + 1) / numPaletteEntries) + (maxValue - minValue + 1) % numPaletteEntries);
}
int[] imageData = new int[numDisplayedPaletteEntries];
int i, j;
int numPaletteEntriesLessOne = numPaletteEntries - 1;
if (!isReversed && orientation == VERTICAL_ORIENTATION) {
if (!categorical) {
for (i = 0; i < numPaletteEntries; i++) {
j = (int) ((Math.pow((1 - ((double) (i) / numPaletteEntriesLessOne)), gamma)) * numPaletteEntriesLessOne);
imageData[i] = paletteData[j];
}
} else { // it is categorical
for (i = 0; i < numDisplayedPaletteEntries; i++) {
j = (int) (i % numPaletteEntries);
imageData[numDisplayedPaletteEntries - 1 - i] = paletteData[j];
}
}
image = createImage(new MemoryImageSource(1, numDisplayedPaletteEntries, imageData, 0, 1));
} else if (!isReversed && orientation == HORIZONTAL_ORIENTATION) {
for (i = 0; i < numPaletteEntries; i++) {
j = (int)((Math.pow(((double)(i) / numPaletteEntriesLessOne), gamma)) * numPaletteEntriesLessOne);
imageData[i] = paletteData[j];
}
image = createImage(new MemoryImageSource(numPaletteEntries, 1, imageData, 0, 1));
} else if (isReversed && orientation == VERTICAL_ORIENTATION) {
if (!categorical) {
for (i = 0; i < numPaletteEntries; i++) {
j = (int) ((Math.pow(((double) (i) / numPaletteEntriesLessOne), gamma)) * numPaletteEntriesLessOne);
imageData[i] = paletteData[j];
}
} else { // it is categorical
for (i = 0; i < numDisplayedPaletteEntries; i++) {
j = (int) (numPaletteEntries - i % numPaletteEntries - 1);
imageData[numDisplayedPaletteEntries - 1 - i] = paletteData[j];
}
}
image = createImage(new MemoryImageSource(1, numDisplayedPaletteEntries, imageData, 0, 1));
} else if (isReversed && orientation == HORIZONTAL_ORIENTATION) {
for (i = 0; i < numPaletteEntries; i++) {
j = (int)((Math.pow((1 - ((double)(i) / numPaletteEntriesLessOne)), gamma)) * numPaletteEntriesLessOne);
imageData[i] = paletteData[j];
}
image = createImage(new MemoryImageSource(imageData.length, 1, imageData, 0, 1));
}
g.drawImage(image, 0, 0, width, height, this);
if (!isSelected) {
g.setColor(Color.black);
g.drawRect(0, 0, width - 1, height - 1);
} else {
g.setColor(Color.white);
g.drawRect(1, 1, width - 3, height - 3);
g.setColor(Color.red);
g.drawRect(0, 0, width - 1, height - 1);
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private void readPalette() {
RandomAccessFile rIn = null;
ByteBuffer buf = null;
int i;
try {
if (paletteFile != null) {
// see if the file exists, if not, set it to the default palette.
File file = new File(paletteFile);
numPaletteEntries = (int) (file.length() / 4);
buf = ByteBuffer.allocate(numPaletteEntries * 4);
rIn = new RandomAccessFile(paletteFile, "r");
FileChannel inChannel = rIn.getChannel();
inChannel.position(0);
inChannel.read(buf);
// Check the byte order.
buf.order(ByteOrder.LITTLE_ENDIAN);
buf.rewind();
IntBuffer ib = buf.asIntBuffer();
paletteData = new int[numPaletteEntries];
ib.get(paletteData);
ib = null;
}
} catch (Exception e) {
System.err.println("Caught exception: " + e.toString());
System.err.println(e.getStackTrace());
} finally {
if (rIn != null) {
try{ rIn.close(); } catch (Exception e){}
}
}
}
}