summaryrefslogtreecommitdiffstats
path: root/src/demos/hdr/RGBE.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/demos/hdr/RGBE.java')
-rwxr-xr-xsrc/demos/hdr/RGBE.java452
1 files changed, 0 insertions, 452 deletions
diff --git a/src/demos/hdr/RGBE.java b/src/demos/hdr/RGBE.java
deleted file mode 100755
index 9c83ae6..0000000
--- a/src/demos/hdr/RGBE.java
+++ /dev/null
@@ -1,452 +0,0 @@
-package demos.hdr;
-
-import java.io.*;
-import java.util.regex.*;
-
-/** This file contains code to read and write four byte rgbe file format
- developed by Greg Ward. It handles the conversions between rgbe and
- pixels consisting of floats. The data is assumed to be an array of floats.
- By default there are three floats per pixel in the order red, green, blue.
- (RGBE_DATA_??? values control this.) Only the mimimal header reading and
- writing is implemented. Each routine does error checking and will return
- a status value as defined below. This code is intended as a skeleton so
- feel free to modify it to suit your needs. <P>
-
- Ported to Java and restructured by Kenneth Russell. <BR>
- posted to http://www.graphics.cornell.edu/~bjw/ <BR>
- written by Bruce Walter ([email protected]) 5/26/95 <BR>
- based on code written by Greg Ward <BR>
-*/
-
-public class RGBE {
- // Flags indicating which fields in a Header are valid
- private static final int VALID_PROGRAMTYPE = 0x01;
- private static final int VALID_GAMMA = 0x02;
- private static final int VALID_EXPOSURE = 0x04;
-
- private static final String gammaString = "GAMMA=";
- private static final String exposureString = "EXPOSURE=";
-
- private static final Pattern widthHeightPattern = Pattern.compile("-Y (\\d+) \\+X (\\d+)");
-
- public static class Header {
- // Indicates which fields are valid
- private int valid;
-
- // Listed at beginning of file to identify it after "#?".
- // Defaults to "RGBE"
- private String programType;
-
- // Image has already been gamma corrected with given gamma.
- // Defaults to 1.0 (no correction)
- private float gamma;
-
- // A value of 1.0 in an image corresponds to <exposure>
- // watts/steradian/m^2. Defaults to 1.0.
- private float exposure;
-
- // Width and height of image
- private int width;
- private int height;
-
- private Header(int valid,
- String programType,
- float gamma,
- float exposure,
- int width,
- int height) {
- this.valid = valid;
- this.programType = programType;
- this.gamma = gamma;
- this.exposure = exposure;
- this.width = width;
- this.height = height;
- }
-
- public boolean isProgramTypeValid() { return ((valid & VALID_PROGRAMTYPE) != 0); }
- public boolean isGammaValid() { return ((valid & VALID_GAMMA) != 0); }
- public boolean isExposureValid() { return ((valid & VALID_EXPOSURE) != 0); }
-
- public String getProgramType() { return programType; }
- public float getGamma() { return gamma; }
- public float getExposure() { return exposure; }
- public int getWidth() { return width; }
- public int getHeight() { return height; }
-
- public String toString() {
- StringBuffer buf = new StringBuffer();
- if (isProgramTypeValid()) {
- buf.append(" Program type: ");
- buf.append(getProgramType());
- }
- buf.append(" Gamma");
- if (isGammaValid()) {
- buf.append(" [valid]");
- }
- buf.append(": ");
- buf.append(getGamma());
- buf.append(" Exposure");
- if (isExposureValid()) {
- buf.append(" [valid]");
- }
- buf.append(": ");
- buf.append(getExposure());
- buf.append(" Width: ");
- buf.append(getWidth());
- buf.append(" Height: ");
- buf.append(getHeight());
- return buf.toString();
- }
- }
-
- public static Header readHeader(DataInputStream in) throws IOException {
- int valid = 0;
- String programType = null;
- float gamma = 1.0f;
- float exposure = 1.0f;
- int width = 0;
- int height = 0;
-
- String buf = in.readLine();
- if (buf == null) {
- throw new IOException("Unexpected EOF reading magic token");
- }
- if (buf.charAt(0) == '#' && buf.charAt(1) == '?') {
- valid |= VALID_PROGRAMTYPE;
- programType = buf.substring(2);
- buf = in.readLine();
- if (buf == null) {
- throw new IOException("Unexpected EOF reading line after magic token");
- }
- }
-
- boolean foundFormat = false;
- boolean done = false;
- while (!done) {
- if (buf.equals("FORMAT=32-bit_rle_rgbe")) {
- foundFormat = true;
- } else if (buf.startsWith(gammaString)) {
- valid |= VALID_GAMMA;
- gamma = Float.parseFloat(buf.substring(gammaString.length()));
- } else if (buf.startsWith(exposureString)) {
- valid |= VALID_EXPOSURE;
- exposure = Float.parseFloat(buf.substring(exposureString.length()));
- } else {
- Matcher m = widthHeightPattern.matcher(buf);
- if (m.matches()) {
- width = Integer.parseInt(m.group(2));
- height = Integer.parseInt(m.group(1));
- done = true;
- }
- }
-
- if (!done) {
- buf = in.readLine();
- if (buf == null) {
- throw new IOException("Unexpected EOF reading header");
- }
- }
- }
-
- if (!foundFormat) {
- throw new IOException("No FORMAT specifier found");
- }
-
- return new Header(valid, programType, gamma, exposure, width, height);
- }
-
- /** Simple read routine. Will not correctly handle run length encoding. */
- public static void readPixels(DataInputStream in, float[] data, int numpixels) throws IOException {
- byte[] rgbe = new byte[4];
- float[] rgb = new float[3];
- int offset = 0;
-
- while(numpixels-- > 0) {
- int numRead = in.read(rgbe);
- if (numRead < 4) {
- throw new IOException("Only able to read " + numRead + " out of expected " + rgbe.length + " bytes");
- }
- rgbe2float(rgb, rgbe, 0);
- data[offset++] = rgb[0];
- data[offset++] = rgb[1];
- data[offset++] = rgb[2];
- }
- }
-
- public static void readPixelsRaw(DataInputStream in, byte[] data, int offset, int numpixels) throws IOException {
- int numExpected = 4 * numpixels;
- int numRead = in.read(data, offset, numExpected);
- if (numRead < numExpected)
- throw new IOException("Error reading raw pixels: got " + numRead + " bytes, expected " + numExpected);
- }
-
- public static void readPixelsRawRLE(DataInputStream in, byte[] data, int offset,
- int scanline_width, int num_scanlines) throws IOException {
- byte[] rgbe = new byte[4];
- byte[] scanline_buffer = null;
- int ptr, ptr_end;
- int count;
- byte[] buf = new byte[2];
-
- if ((scanline_width < 8)||(scanline_width > 0x7fff)) {
- /* run length encoding is not allowed so read flat*/
- readPixelsRaw(in, data, offset, scanline_width*num_scanlines);
- }
-
- /* read in each successive scanline */
- while (num_scanlines > 0) {
- if (in.read(rgbe) < rgbe.length) {
- throw new IOException("Error reading bytes: expected " + rgbe.length);
- }
-
- if ((rgbe[0] != 2)||(rgbe[1] != 2)||((rgbe[2] & 0x80) != 0)) {
- /* this file is not run length encoded */
- data[offset++] = rgbe[0];
- data[offset++] = rgbe[1];
- data[offset++] = rgbe[2];
- data[offset++] = rgbe[3];
- readPixelsRaw(in, data, offset, scanline_width*num_scanlines-1);
- }
-
- if ((((rgbe[2] & 0xFF)<<8) | (rgbe[3] & 0xFF)) != scanline_width) {
- throw new IOException("Wrong scanline width " +
- (((rgbe[2] & 0xFF)<<8) | (rgbe[3] & 0xFF)) +
- ", expected " + scanline_width);
- }
-
- if (scanline_buffer == null) {
- scanline_buffer = new byte[4*scanline_width];
- }
-
- ptr = 0;
- /* read each of the four channels for the scanline into the buffer */
- for (int i=0; i<4; i++) {
- ptr_end = (i+1)*scanline_width;
- while(ptr < ptr_end) {
- if (in.read(buf) < buf.length) {
- throw new IOException("Error reading 2-byte buffer");
- }
- if ((buf[0] & 0xFF) > 128) {
- /* a run of the same value */
- count = (buf[0] & 0xFF)-128;
- if ((count == 0)||(count > ptr_end - ptr)) {
- throw new IOException("Bad scanline data");
- }
- while(count-- > 0)
- scanline_buffer[ptr++] = buf[1];
- }
- else {
- /* a non-run */
- count = buf[0] & 0xFF;
- if ((count == 0)||(count > ptr_end - ptr)) {
- throw new IOException("Bad scanline data");
- }
- scanline_buffer[ptr++] = buf[1];
- if (--count > 0) {
- if (in.read(scanline_buffer, ptr, count) < count) {
- throw new IOException("Error reading non-run data");
- }
- ptr += count;
- }
- }
- }
- }
- /* copy byte data to output */
- for(int i = 0; i < scanline_width; i++) {
- data[offset++] = scanline_buffer[i];
- data[offset++] = scanline_buffer[i+scanline_width];
- data[offset++] = scanline_buffer[i+2*scanline_width];
- data[offset++] = scanline_buffer[i+3*scanline_width];
- }
- num_scanlines--;
- }
- }
-
- /** Standard conversion from float pixels to rgbe pixels. */
- public static void float2rgbe(byte[] rgbe, float red, float green, float blue) {
- float v;
- int e;
-
- v = red;
- if (green > v) v = green;
- if (blue > v) v = blue;
- if (v < 1e-32f) {
- rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
- }
- else {
- FracExp fe = frexp(v);
- v = (float) (fe.getFraction() * 256.0 / v);
- rgbe[0] = (byte) (red * v);
- rgbe[1] = (byte) (green * v);
- rgbe[2] = (byte) (blue * v);
- rgbe[3] = (byte) (fe.getExponent() + 128);
- }
- }
-
- /** Standard conversion from rgbe to float pixels. Note: Ward uses
- ldexp(col+0.5,exp-(128+8)). However we wanted pixels in the
- range [0,1] to map back into the range [0,1]. */
- public static void rgbe2float(float[] rgb, byte[] rgbe, int startRGBEOffset) {
- float f;
-
- if (rgbe[startRGBEOffset + 3] != 0) { /*nonzero pixel*/
- f = (float) ldexp(1.0,(rgbe[startRGBEOffset + 3] & 0xFF)-(128+8));
- rgb[0] = (rgbe[startRGBEOffset + 0] & 0xFF) * f;
- rgb[1] = (rgbe[startRGBEOffset + 1] & 0xFF) * f;
- rgb[2] = (rgbe[startRGBEOffset + 2] & 0xFF) * f;
- } else {
- rgb[0] = 0;
- rgb[1] = 0;
- rgb[2] = 0;
- }
- }
-
- public static double ldexp(double value, int exp) {
- if(!finite(value)||value==0.0) return value;
- value = scalbn(value,exp);
- // No good way to indicate errno (want to avoid throwing
- // exceptions because don't know about stability of calculations)
- // if(!finite(value)||value==0.0) errno = ERANGE;
- return value;
- }
-
- //----------------------------------------------------------------------
- // Internals only below this point
- //
-
- //----------------------------------------------------------------------
- // Math routines, some fdlibm-derived
- //
-
- static class FracExp {
- private double fraction;
- private int exponent;
-
- public FracExp(double fraction, int exponent) {
- this.fraction = fraction;
- this.exponent = exponent;
- }
-
- public double getFraction() { return fraction; }
- public int getExponent() { return exponent; }
- }
-
- private static final double two54 = 1.80143985094819840000e+16; /* 43500000 00000000 */
- private static final double twom54 = 5.55111512312578270212e-17; /* 0x3C900000 0x00000000 */
- private static final double huge = 1.0e+300;
- private static final double tiny = 1.0e-300;
-
- private static int hi(double x) {
- long bits = Double.doubleToRawLongBits(x);
- return (int) (bits >>> 32);
- }
-
- private static int lo(double x) {
- long bits = Double.doubleToRawLongBits(x);
- return (int) bits;
- }
-
- private static double fromhilo(int hi, int lo) {
- return Double.longBitsToDouble((((long) hi) << 32) |
- (((long) lo) & 0xFFFFFFFFL));
- }
-
- private static FracExp frexp(double x) {
- int hx = hi(x);
- int ix = 0x7fffffff&hx;
- int lx = lo(x);
- int e = 0;
- if(ix>=0x7ff00000||((ix|lx)==0))
- return new FracExp(x, e); /* 0,inf,nan */
- if (ix<0x00100000) { /* subnormal */
- x *= two54;
- hx = hi(x);
- ix = hx&0x7fffffff;
- e = -54;
- }
- e += (ix>>20)-1022;
- hx = (hx&0x800fffff)|0x3fe00000;
- lx = lo(x);
- return new FracExp(fromhilo(hx, lx), e);
- }
-
- private static boolean finite(double x) {
- int hx;
- hx = hi(x);
- return (((hx&0x7fffffff)-0x7ff00000)>>31) != 0;
- }
-
- /**
- * copysign(double x, double y) <BR>
- * copysign(x,y) returns a value with the magnitude of x and
- * with the sign bit of y.
- */
- private static double copysign(double x, double y) {
- return fromhilo((hi(x)&0x7fffffff)|(hi(y)&0x80000000), lo(x));
- }
-
- /**
- * scalbn (double x, int n) <BR>
- * scalbn(x,n) returns x* 2**n computed by exponent
- * manipulation rather than by actually performing an
- * exponentiation or a multiplication.
- */
- private static double scalbn(double x, int n) {
- int hx = hi(x);
- int lx = lo(x);
- int k = (hx&0x7ff00000)>>20; /* extract exponent */
- if (k==0) { /* 0 or subnormal x */
- if ((lx|(hx&0x7fffffff))==0) {
- return x; /* +-0 */
- }
- x *= two54;
- hx = hi(x);
- k = ((hx&0x7ff00000)>>20) - 54;
- if (n< -50000) {
- return tiny*x; /*underflow*/
- }
- }
- if (k==0x7ff) {
- return x+x; /* NaN or Inf */
- }
- k = k+n;
- if (k > 0x7fe) {
- return huge*copysign(huge,x); /* overflow */
- }
- if (k > 0) {
- /* normal result */
- return fromhilo((hx&0x800fffff)|(k<<20), lo(x));
- }
- if (k <= -54) {
- if (n > 50000) {
- /* in case integer overflow in n+k */
- return huge*copysign(huge,x); /* overflow */
- } else {
- return tiny*copysign(tiny,x); /* underflow */
- }
- }
- k += 54; /* subnormal result */
- x = fromhilo((hx&0x800fffff)|(k<<20), lo(x));
- return x*twom54;
- }
-
- //----------------------------------------------------------------------
- // Test harness
- //
-
- public static void main(String[] args) {
- for (int i = 0; i < args.length; i++) {
- try {
- DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(args[i])));
- Header header = RGBE.readHeader(in);
- System.err.println("Header for file \"" + args[i] + "\":");
- System.err.println(" " + header);
- byte[] data = new byte[header.getWidth() * header.getHeight() * 4];
- readPixelsRawRLE(in, data, 0, header.getWidth(), header.getHeight());
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-}