import com.sun.media.jai.codec.ImageCodec;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.FileNotFoundException;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class OwnPanel
extends JComponent
{
private static final long serialVersionUID = 1L;
private final OwnImage img;
private OwnPanel(OwnImage img)
{
super();
if(img == null) {
throw new NullPointerException("img may not be null");
}
this.img = img;
Dimension size = new Dimension(img.getWidth(), img.getHeight());
setMinimumSize(new Dimension(1, 1));
setPreferredSize(size);
setSize(size);
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
long start = System.currentTimeMillis();
g.drawImage(img, 0, 0, getWidth(), getHeight(), null);
System.out.println("Conversion and repaint took " + (System.currentTimeMillis() - start) + "ms");
}
public static void main(String[] args)
{
if(args == null || args.length == 0) {
args = new String[] {"tiff16bit.png"};
}
JFrame f = new JFrame("OwnImageTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cp = f.getContentPane();
final JSlider upper = new JSlider(JSlider.VERTICAL);
final JSlider lower = new JSlider(JSlider.VERTICAL);
OwnImage oi = new OwnImage(new File(args[0]).getAbsoluteFile());
final OwnPanel op = new OwnPanel(oi);
cp.setLayout(new BorderLayout());
cp.add(op, BorderLayout.CENTER);
cp.add(upper, BorderLayout.EAST);
cp.add(lower, BorderLayout.WEST);
upper.setMaximum(0xFFFF);
upper.setMinimum(0);
upper.setValue(oi.getOgDraw());
upper.addChangeListener(new ChangeListener()
{
@Override
public void stateChanged(ChangeEvent e)
{
int v = upper.getValue();
op.img.setOgDraw(v);
lower.setMaximum(v);
op.repaint();
}
});
lower.setMaximum(0xFFFF);
lower.setMinimum(0);
lower.setValue(oi.getUgDraw());
lower.addChangeListener(new ChangeListener()
{
@Override
public void stateChanged(ChangeEvent e)
{
int v = lower.getValue();
op.img.setUgDraw(v);
upper.setMinimum(v);
op.repaint();
}
});
f.pack();
f.setVisible(true);
}
}
class OwnImage
extends BufferedImage
{
private final int[] backUp;
public OwnImage(File f)
{
this(new Loader(f));
}
private OwnImage(Loader l)
{
super(l.cm, l.data, false, null);
backUp = l.data.getPixels(0, 0, getWidth(), getHeight(), (int[]) null);
}
public synchronized int getUgDraw()
{
return ((OwnColorModel) getColorModel()).ug;
}
public synchronized int getOgDraw()
{
return ((OwnColorModel) getColorModel()).og;
}
public synchronized void setUgDraw(int ug)
{
((OwnColorModel) getColorModel()).setUg(ug);
restore();
}
public synchronized void setOgDraw(int og)
{
((OwnColorModel) getColorModel()).setOg(og);
restore();
}
public synchronized void setUgOgDraw(int ug, int og)
{
((OwnColorModel) getColorModel()).setBorders(ug, og);
restore();
}
@Override
public void setRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)
{
int yoff = offset;
int off, rgb;
short[] pixel = null;
for(int y = startY; y < startY + h; y++, yoff+=scansize) {
off = yoff;
for(int x = startX; x < startX + w; x++) {
pixel = (short[]) getColorModel().getDataElements(rgbArray[off++], pixel);
rgb = pixel[0] & 0xFFFF;
backUp[y * getWidth() + x] = rgb;
getRaster().setDataElements(x, y, pixel);
}
}
}
@Override
public synchronized void setRGB(int x, int y, int rgb)
{
short[] pi = (short[]) getColorModel().getDataElements(rgb, null);
rgb = pi[0] & 0xFFFF;
backUp[y * getWidth() + x] = rgb;
getRaster().setDataElements(x, y, pi);
}
private void restore()
{
getRaster().setPixels(0, 0, getWidth(), getHeight(), backUp);
}
private static class Loader
{
private ColorModel cm;
private WritableRaster data;
private Loader(File f)
{
RenderedImage ri = null;
try {
//Rendered Image erstellen
ri = ImageCodec.createImageDecoder("TIFF", f, null).decodeAsRenderedImage();
} catch(FileNotFoundException e) {
e.printStackTrace();
return;
}
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
int w = ri.getWidth();
int h = ri.getHeight();
data = Raster.createPackedRaster(DataBuffer.TYPE_USHORT, w, h, 1, 16, new Point());
Raster raster = ri.getData();
ColorModel model = ri.getColorModel();
Object buffer = null;
int numComponents = model.getNumComponents();
int type = model.getTransferType();
int red = 0, green = 0, blue = 0;
switch(type) {
case DataBuffer.TYPE_BYTE:
buffer = new byte[numComponents];
break;
case DataBuffer.TYPE_SHORT:
case DataBuffer.TYPE_USHORT:
buffer = new short[numComponents];
break;
case DataBuffer.TYPE_INT:
buffer = new int[numComponents];
break;
default:
throw new UnsupportedOperationException("unsupported tranfer type");
}
int c = max;
for(int x = 0; x < w; x++) {
for(int y = 0; y < h; y++) {
raster.getDataElements(x, y, buffer);
if(type != DataBuffer.TYPE_SHORT && type != DataBuffer.TYPE_USHORT) {
red = model.getRed(buffer) << 8;
green = model.getGreen(buffer) << 8;
blue = model.getBlue(buffer) << 8;
} else {
if(numComponents == 1) {
c = ((short[]) buffer)[0] & 0xFFFF;
} else {
red = ((short[]) buffer)[0] & 0xFFFF;
green = ((short[]) buffer)[1] & 0xFFFF;
blue = ((short[]) buffer)[2] & 0xFFFF;
}
}
if(red != green || red != blue || green != blue) {
red = (int) (red * 0.3 + green * 0.59 + blue * 0.11);
}
c = red & 0xFFFF;
data.setSample(x, y, 0, c);
if(min > c) {
min = c;
}
if(max < c) {
max = c;
}
}
}
cm = new OwnColorModel(min, max);
}
}
private static class OwnColorModel
extends ColorModel
{
private int og, ug;
private double ratio;
public OwnColorModel(int ug, int og)
{
super(8);
setBorders(ug, og);
}
@Override
public boolean isCompatibleRaster(Raster raster)
{
return true;
}
@Override
public int getRed(int pixel)
{
return pixel2RGB(pixel);
}
@Override
public int getGreen(int pixel)
{
return pixel2RGB(pixel);
}
@Override
public int getBlue(int pixel)
{
return pixel2RGB(pixel);
}
@Override
public int getAlpha(int pixel)
{
return 0xFF;
}
@Override
public int getRGB(Object inData)
{
if(inData == null) {
throw new NullPointerException("inData may not be null");
}
if(inData instanceof byte[]) {
return pixel2RGB(((byte[]) inData)[0]);
} else if(inData instanceof short[]) {
return pixel2RGB(((short[]) inData)[0]);
} else if(inData instanceof int[]) {
return pixel2RGB(((int[]) inData)[0]);
} else {
return 0;
}
}
@Override
public int getRGB(int pixel)
{
return pixel2RGB(pixel);
}
@Override
public Object getDataElements(int rgb, Object pixel)
{
if((rgb & 0xFFFF) != Math.abs(rgb)) {
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = (rgb >> 0) & 0xFF;
if(r != g || r != b || g != b) {
r = (int) (r * 0.3 + g * 0.59 + b * 0.11) & 0xFF;
}
rgb = r << 8 | r;
}
if(pixel == null) {
pixel = new short[1];
}
if(pixel instanceof byte[]) {
byte[] b = (byte[]) pixel;
b[0] = (byte) rgb;
if(b.length > 1) {
throw new IllegalArgumentException("no more components");
}
} else if(pixel instanceof short[]) {
short[] b = (short[]) pixel;
b[0] = (short) rgb;
if(b.length > 1) {
throw new IllegalArgumentException("no more components");
}
}
if(pixel instanceof int[]) {
int[] b = (int[]) pixel;
b[0] = rgb;
if(b.length > 1) {
throw new IllegalArgumentException("no more components");
}
}
return pixel;
}
private void setUg(int ug)
{
setBorders(ug, og);
}
private void setOg(int og)
{
setBorders(ug, og);
}
private void setBorders(int ug, int og)
{
og &= 0xFFFF;
ug &= 0xFFFF;
this.ug = Math.min(ug, og);
this.og = Math.max(ug, og);
ratio = 65535.0 / (this.og - this.ug);
}
private final int pixel2RGB(int pixel)
{
pixel &= 0xFFFF;
pixel = ((int) ((pixel - ug) * ratio) >> 8) & 0xFF;
return pixel | pixel << 8 | pixel << 16 | 0xFF000000;
}
}
}