code: package org.sunflow.image.readers;
  
  import java.io.BufferedInputStream;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  
  import org.sunflow.image.Bitmap;
  import org.sunflow.image.BitmapReader;
  import org.sunflow.image.formats.BitmapRGBE;
  
  public class HDRBitmapReader implements BitmapReader {
      public Bitmap load(String filename, boolean isLinear) throws IOException, BitmapFormatException {
          // load radiance rgbe file
          InputStream f = new BufferedInputStream(new FileInputStream(filename));
          // parse header
          boolean parseWidth = false, parseHeight = false;
          int width = 0, height = 0;
          int last = 0;
          while (width == 0 || height == 0 || last != '\n') {
              int n = f.read();
              switch (n) {
                  case 'Y':
                      parseHeight = last == '-';
                      parseWidth = false;
                      break;
                  case 'X':
                      parseHeight = false;
                      parseWidth = last == '+';
                      break;
                  case ' ':
                      parseWidth &= width == 0;
                      parseHeight &= height == 0;
                      break;
                  case '0':
                  case '1':
                  case '2':
                  case '3':
                  case '4':
                  case '5':
                  case '6':
                  case '7':
                  case '8':
                  case '9':
                      if (parseHeight)
                          height = 10 * height + (n - '0');
                      else if (parseWidth)
                          width = 10 * width + (n - '0');
                      break;
                  default:
                      parseWidth = parseHeight = false;
                      break;
              }
              last = n;
          }
          // allocate image
          int[] pixels = new int[width * height];
          if ((width < 8) || (width > 0x7fff)) {
              // run length encoding is not allowed so read flat
              readFlatRGBE(f, 0, width * height, pixels);
          } else {
              int rasterPos = 0;
              int numScanlines = height;
              int[] scanlineBuffer = new int[4 * width];
              while (numScanlines > 0) {
                  int r = f.read();
                  int g = f.read();
                  int b = f.read();
                  int e = f.read();
                  if ((r != 2) || (g != 2) || ((b & 0x80) != 0)) {
                      // this file is not run length encoded
                      pixels[rasterPos] = (r << 24) | (g << 16) | (b << 8) | e;
                      readFlatRGBE(f, rasterPos + 1, width * numScanlines - 1, pixels);
                      break;
                  }
  
                  if (((b << 8) | e) != width)
                      throw new BitmapFormatException("Invalid scanline width");
                  int p = 0;
                  // read each of the four channels for the scanline into
                  // the buffer
                  for (int i = 0; i < 4; i++) {
                      if (p % width != 0)
                          throw new BitmapFormatException("Unaligned access to scanline data");
                      int end = (i + 1) * width;
                      while (p < end) {
                          int b0 = f.read();
                          int b1 = f.read();
                          if (b0 > 128) {
                              // a run of the same value
                              int count = b0 - 128;
                              if ((count == 0) || (count > (end - p)))
                                  throw new BitmapFormatException("Bad scanline data - invalid RLE run");
  
                              while (count-- > 0) {
                                  scanlineBuffer[p] = b1;
                                  p++;
                              }
                          } else {
                              // a non-run
                              int count = b0;
                              if ((count == 0) || (count > (end - p)))
                                  throw new BitmapFormatException("Bad scanline data - invalid count");
                              scanlineBuffer[p] = b1;
                              p++;
                              if (--count > 0) {
                                  for (int x = 0; x < count; x++)
                                      scanlineBuffer[p + x] = f.read();
                                  p += count;
                              }
                          }
                      }
                  }
                  // now convert data from buffer into floats
                  for (int i = 0; i < width; i++) {
                      r = scanlineBuffer[i];
                      g = scanlineBuffer[i + width];
                      b = scanlineBuffer[i + 2 * width];
                      e = scanlineBuffer[i + 3 * width];
                      pixels[rasterPos] = (r << 24) | (g << 16) | (b << 8) | e;
                      rasterPos++;
                  }
                  numScanlines--;
              }
          }
          f.close();
          // flip image
          for (int y = 0, i = 0, ir = (height - 1) * width; y < height / 2; y++, ir -= width) {
              for (int x = 0, i2 = ir; x < width; x++, i++, i2++) {
                  int t = pixels[i];
                  pixels[i] = pixels[i2];
                  pixels[i2] = t;
              }
          }
          return new BitmapRGBE(width, height, pixels);
      }
  
      private void readFlatRGBE(InputStream f, int rasterPos, int numPixels, int[] pixels) throws IOException {
          while (numPixels-- > 0) {
              int r = f.read();
              int g = f.read();
              int b = f.read();
              int e = f.read();
              pixels[rasterPos] = (r << 24) | (g << 16) | (b << 8) | e;
              rasterPos++;
          }
      }
  }