123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- /// <reference path="../../../dist/preview release/babylon.d.ts"/>
- module BABYLON.Internals {
- export interface HDRInfo {
- height: number;
- width: number;
- dataPosition: number;
- };
- export class HDRTools {
- private static Ldexp(mantissa: number, exponent: number): number {
- if (exponent > 1023) {
- return mantissa * Math.pow(2, 1023) * Math.pow(2, exponent - 1023);
- }
- if (exponent < -1074) {
- return mantissa * Math.pow(2, -1074) * Math.pow(2, exponent + 1074);
- }
- return mantissa * Math.pow(2, exponent);
- }
- private static Rgbe2float(float32array: Float32Array,
- red: number, green: number, blue: number, exponent: number,
- index: number)
- {
- if (exponent > 0) { /*nonzero pixel*/
- exponent = this.Ldexp(1.0, exponent - (128 + 8));
- float32array[index + 0] = red * exponent;
- float32array[index + 1] = green * exponent;
- float32array[index + 2] = blue * exponent;
- }
- else {
- float32array[index + 0] = 0;
- float32array[index + 1] = 0;
- float32array[index + 2] = 0;
- }
- }
- private static readStringLine(uint8array: Uint8Array, startIndex: number): string {
- var line = "";
- var character = "";
- for(var i = startIndex; i < uint8array.length - startIndex; i++) {
- character = String.fromCharCode(uint8array[i]);
- if (character == "\n") {
- break;
- }
- line += character;
- }
- return line;
- }
- /* minimal header reading. modify if you want to parse more information */
- public static RGBE_ReadHeader(uint8array: Uint8Array) : HDRInfo {
- var height: number = 0;
- var width: number = 0;
-
- var line = this.readStringLine(uint8array, 0);
- if (line[0] != '#' || line[1] != '?') {
- throw "Bad HDR Format.";
- }
- var endOfHeader = false;
- var findFormat = false;
- var lineIndex:number = 0;
- do {
- lineIndex += (line.length + 1);
- line = this.readStringLine(uint8array, lineIndex);
- if (line == "FORMAT=32-bit_rle_rgbe") {
- findFormat = true;
- }
- else if (line.length == 0) {
- endOfHeader = true;
- }
- } while (!endOfHeader);
- if (!findFormat) {
- throw "HDR Bad header format, unsupported FORMAT";
- }
- lineIndex += (line.length + 1);
- line = this.readStringLine(uint8array, lineIndex);
-
- var sizeRegexp = /^\-Y (.*) \+X (.*)$/g;
- var match = sizeRegexp.exec(line);
- // TODO. Support +Y and -X if needed.
- if (match.length < 3) {
- throw "HDR Bad header format, no size";
- }
- width = parseInt(match[2]);
- height = parseInt(match[1]);
- if (width < 8 || width > 0x7fff) {
- throw "HDR Bad header format, unsupported size";
- }
- lineIndex += (line.length + 1);
- return {
- height: height,
- width: width,
- dataPosition: lineIndex
- };
- }
- public static GetCubeMapTextureData(buffer: ArrayBuffer, size: number) : CubeMapInfo {
- var uint8array = new Uint8Array(buffer);
- var hdrInfo = this.RGBE_ReadHeader(uint8array);
- var data = this.RGBE_ReadPixels_RLE(uint8array, hdrInfo);
- var cubeMapData = PanoramaToCubeMapTools.ConvertPanoramaToCubemap(data, hdrInfo.width, hdrInfo.height, size);
- return cubeMapData;
- }
- public static RGBE_ReadPixels(uint8array:Uint8Array, hdrInfo:HDRInfo): Float32Array {
- // Keep for multi format supports.
- return this.RGBE_ReadPixels_RLE(uint8array, hdrInfo);
- }
- private static RGBE_ReadPixels_RLE(uint8array:Uint8Array, hdrInfo:HDRInfo): Float32Array {
- var num_scanlines = hdrInfo.height;
- var scanline_width = hdrInfo.width;
- var a: number, b: number, c: number, d: number, count: number;
- var dataIndex = hdrInfo.dataPosition;
- var index = 0, endIndex = 0, i = 0;
- var scanLineArrayBuffer = new ArrayBuffer(scanline_width * 4); // four channel R G B E
- var scanLineArray = new Uint8Array(scanLineArrayBuffer);
- // 3 channels of 4 bytes per pixel in float.
- var resultBuffer = new ArrayBuffer(hdrInfo.width * hdrInfo.height * 4 * 3);
- var resultArray = new Float32Array(resultBuffer);
- // read in each successive scanline
- while(num_scanlines > 0) {
- a = uint8array[dataIndex++];
- b = uint8array[dataIndex++];
- c = uint8array[dataIndex++];
- d = uint8array[dataIndex++];
- if (a != 2 || b != 2 || (c & 0x80)) {
- // this file is not run length encoded
- throw "HDR Bad header format, not RLE";
- }
- if (((c<<8) | d) != scanline_width) {
- throw "HDR Bad header format, wrong scan line width";
- }
- index = 0;
- // read each of the four channels for the scanline into the buffer
- for(i = 0; i < 4; i++) {
- endIndex = (i + 1) * scanline_width;
- while(index < endIndex) {
- a = uint8array[dataIndex++];
- b = uint8array[dataIndex++];
- if (a > 128) {
- // a run of the same value
- count = a - 128;
- if ((count == 0) || (count > endIndex - index)) {
- throw "HDR Bad Format, bad scanline data (run)";
- }
- while(count-- > 0) {
- scanLineArray[index++] = b;
- }
- }
- else {
- // a non-run
- count = a;
- if ((count == 0) || (count > endIndex - index)) {
- throw "HDR Bad Format, bad scanline data (non-run)";
- }
- scanLineArray[index++] = b;
- if (--count > 0) {
- for (var j = 0; j < count; j++) {
- scanLineArray[index++] = uint8array[dataIndex++];
- }
- }
- }
- }
- }
- // now convert data from buffer into floats
- for(i = 0; i < scanline_width; i++) {
- a = scanLineArray[i];
- b = scanLineArray[i + scanline_width];
- c = scanLineArray[i + 2 * scanline_width];
- d = scanLineArray[i + 3 * scanline_width];
- this.Rgbe2float(resultArray,
- a, b, c, d,
- (hdrInfo.height - num_scanlines) * scanline_width * 3 + i * 3);
- }
- num_scanlines--;
- }
- return resultArray;
- }
- }
- }
|