package com.revolsys.raster.io.format;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import com.revolsys.io.BaseCloseable;
import com.revolsys.io.endian.EndianOutputStream;
import com.revolsys.util.Property;
public class RasterWriter implements BaseCloseable {
private static final int ELEVATIONS = 9;
private static final byte PROPERTY_BOOLEAN = 1;
private static final byte PROPERTY_BYTE = 2;
private static final byte PROPERTY_DOUBLE = 7;
private static final byte PROPERTY_FLOAT = 6;
private static final byte PROPERTY_INT = 4;
private static final byte PROPERTY_LONG = 5;
private static final byte PROPERTY_SHORT = 3;
private static final byte PROPERTY_STRING = 8;
private final EndianOutputStream out;
public RasterWriter(final OutputStream out) {
this.out = new EndianOutputStream(new BufferedOutputStream(out));
property("TYPE", "RASTER");
property("VERSION", (byte)1);
}
@Override
public void close() {
this.out.flush();
this.out.close();
}
public void property(final String name, final boolean value) {
writeByte(PROPERTY_BOOLEAN);
if (value) {
writeByte(1);
} else {
writeByte(0);
}
}
public void property(final String name, final byte value) {
writeByte(PROPERTY_BYTE);
writeByte(value);
}
public void property(final String name, final double value) {
writeByte(PROPERTY_DOUBLE);
this.out.writeDouble(value);
}
public void property(final String name, final float value) {
writeByte(PROPERTY_FLOAT);
this.out.writeFloat(value);
}
public void property(final String name, final int value) {
writeByte(PROPERTY_INT);
this.out.writeInt(value);
}
public void property(final String name, final long value) {
writeByte(PROPERTY_LONG);
this.out.writeLong(value);
}
public void property(final String name, final Object value) {
if (Property.hasValue(name)) {
if (value == null) {
} else if (value instanceof Boolean) {
property(name, value);
} else if (value instanceof Byte) {
property(name, value);
} else if (value instanceof Short) {
property(name, value);
} else if (value instanceof Integer) {
property(name, value);
} else if (value instanceof Long) {
property(name, value);
} else if (value instanceof Float) {
property(name, value);
} else if (value instanceof Double) {
property(name, value);
} else if (value instanceof String) {
property(name, (String)value);
} else {
property(name, value.toString());
}
}
}
public void property(final String name, final short value) {
writeByte(PROPERTY_SHORT);
this.out.writeShort(value);
}
public void property(final String name, final String value) {
writeByte(PROPERTY_STRING);
this.out.writeBytes(value);
}
public void values(final double offset, final double scale, final double... values) {
writeByte(ELEVATIONS);
int previousValue = 0;
for (final double value : values) {
final int scaledValue = (int)Math.round((value - offset) * scale);
final int delta = scaledValue - previousValue;
varSInt(delta);
previousValue = scaledValue;
}
}
public void varInt(int value) {
while (true) {
if ((value & ~0x7F) == 0) {
writeByte(value);
return;
} else {
writeByte(value & 0x7F | 0x80);
value >>>= 7;
}
}
}
public void varInt(long value) {
while (true) {
while (true) {
if ((value & ~0x7FL) == 0) {
writeByte((int)value);
return;
} else {
writeByte((int)value & 0x7F | 0x80);
value >>>= 7;
}
}
}
}
public void varSInt(int value) {
value = value << 1 ^ value >> 31;
varInt(value);
}
public void varSInt(long value) {
value = value << 1 ^ value >> 63;
varInt(value);
}
private void writeByte(final int value) {
this.out.write(value);
}
}