Skip to content

⬅️ Back to Table of Contents

📄 RGBELoader.js

📊 Analysis Summary

Metric Count
🔧 Functions 10
🧱 Classes 1
📦 Imports 6
📊 Variables & Constants 47

📚 Table of Contents

🛠️ File Location:

📂 examples/jsm/loaders/RGBELoader.js

📦 Imports

Name Source
DataTextureLoader three
DataUtils three
FloatType three
HalfFloatType three
LinearFilter three
LinearSRGBColorSpace three

Variables & Constants

Name Type Kind Value Exported
rgbe_read_error 1 let/var 1
rgbe_write_error 2 let/var 2
rgbe_format_error 3 let/var 3
rgbe_memory_error 4 let/var 4
RGBE_VALID_PROGRAMTYPE 1 let/var 1
RGBE_VALID_FORMAT 2 let/var 2
RGBE_VALID_DIMENSIONS 4 let/var 4
NEWLINE "\n" let/var '\n'
chunkSize 128 let/var 128
p any let/var buffer.pos
i number let/var - 1
len number let/var 0
s string let/var ''
magic_token_re RegExp let/var /^#\?(\S+)/
gamma_re RegExp let/var /^\s*GAMMA\s*=\s*(\d+(\.\d+)?)\s*$/
exposure_re RegExp let/var /^\s*EXPOSURE\s*=\s*(\d+(\.\d+)?)\s*$/
format_re RegExp let/var /^\s*FORMAT=(\S+)\s*$/
dimensions_re RegExp let/var /^\s*\-Y\s+(\d+)\s+\+X\s+(\d+)\s*$/
header { valid: number; string: string; comm... let/var { valid: 0, /* indicate which fields are valid */ string: '', /* the actual h...
line any let/var *not shown*
match any let/var *not shown*
scanline_width any let/var w
data_rgba Uint8Array<ArrayBuffer> let/var new Uint8Array( 4 * w * h )
offset number let/var 0
pos number let/var 0
ptr_end number let/var 4 * scanline_width
rgbeStart Uint8Array<ArrayBuffer> let/var new Uint8Array( 4 )
scanline_buffer Uint8Array<ArrayBuffer> let/var new Uint8Array( ptr_end )
num_scanlines any let/var h
ptr number let/var 0
count any let/var *not shown*
isEncodedRun boolean let/var count > 128
byteValue any let/var buffer[ pos ++ ]
l any let/var scanline_width
off number let/var 0
e any let/var sourceArray[ sourceOffset + 3 ]
scale number let/var Math.pow( 2.0, e - 128.0 ) / 255.0
e any let/var sourceArray[ sourceOffset + 3 ]
scale number let/var Math.pow( 2.0, e - 128.0 ) / 255.0
byteArray Uint8Array<ArrayBuffer> let/var new Uint8Array( buffer )
w number let/var rgbe_header_info.width
h number let/var rgbe_header_info.height
data any let/var *not shown*
type any let/var *not shown*
numElements any let/var *not shown*
floatArray Float32Array<ArrayBuffer> let/var new Float32Array( numElements * 4 )
halfArray Uint16Array<ArrayBuffer> let/var new Uint16Array( numElements * 4 )

Functions

RGBELoader.parse(buffer: ArrayBuffer): DataTextureLoader

JSDoc:

/**
     * Parses the given RGBE texture data.
     *
     * @param {ArrayBuffer} buffer - The raw texture data.
     * @return {DataTextureLoader~TexData} An object representing the parsed texture data.
     */

Parameters:

  • buffer ArrayBuffer

Returns: DataTextureLoader

Calls:

  • String.fromCharCode.apply
  • buffer.subarray
  • chunk.indexOf
  • chunk.slice
  • fgets
  • rgbe_error
  • line.match
  • line.charAt
  • parseFloat
  • parseInt
  • scanline_buffer.set
  • Math.pow
  • DataUtils.toHalfFloat
  • Math.min
  • RGBE_ReadHeader
  • RGBE_ReadPixels_RLE
  • byteArray.subarray
  • RGBEByteToRGBFloat
  • RGBEByteToRGBHalf

Internal Comments:

// adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html (x2)
/* default error routine.  change this to change error handling */ (x2)
/* offsets to red, green, and blue components in a data (float) pixel */ (x2)
//RGBE_DATA_RED = 0, (x2)
//RGBE_DATA_GREEN = 1, (x2)
//RGBE_DATA_BLUE = 2, (x2)
/* number of floats per pixel, use 4 since stored in rgba image format */ (x2)
//RGBE_DATA_SIZE = 4, (x2)
/* flags indicating which fields in an rgbe_header_info are valid */ (x2)
/*for (i=l-1; i>=0; i--) {
                        byteCode = m.charCodeAt(i);
                        if (byteCode > 0x7f && byteCode <= 0x7ff) byteLen++;
                        else if (byteCode > 0x7ff && byteCode <= 0xffff) byteLen += 2;
                        if (byteCode >= 0xDC00 && byteCode <= 0xDFFF) i--; //trail surrogate
                    }*/
/* minimal header reading.  modify if you want to parse more information */ (x2)
// regexes to parse header info fields (x2)
// RGBE format header struct (x2)
/* if you want to require the magic token then uncomment the next line */
// run length encoding is not allowed so read flat (x2)
// this file is not run length encoded
// return the flat buffer
// read in each successive scanline
// read each of the four channels for the scanline into the buffer (x2)
// first red, then green, then blue, then exponent (x2)
// a (encoded) run of the same value (x2)
// a literal-run (x4)
// now convert data from buffer into rgba (x2)
// first red, then green, then blue, then exponent (alpha) (x2)
// clamping to 65504, the maximum representable value in float16 (x4)

Code
parse( buffer ) {

        // adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html

        const
            /* default error routine.  change this to change error handling */
            rgbe_read_error = 1,
            rgbe_write_error = 2,
            rgbe_format_error = 3,
            rgbe_memory_error = 4,
            rgbe_error = function ( rgbe_error_code, msg ) {

                switch ( rgbe_error_code ) {

                    case rgbe_read_error: throw new Error( 'THREE.RGBELoader: Read Error: ' + ( msg || '' ) );
                    case rgbe_write_error: throw new Error( 'THREE.RGBELoader: Write Error: ' + ( msg || '' ) );
                    case rgbe_format_error: throw new Error( 'THREE.RGBELoader: Bad File Format: ' + ( msg || '' ) );
                    default:
                    case rgbe_memory_error: throw new Error( 'THREE.RGBELoader: Memory Error: ' + ( msg || '' ) );

                }

            },

            /* offsets to red, green, and blue components in a data (float) pixel */
            //RGBE_DATA_RED = 0,
            //RGBE_DATA_GREEN = 1,
            //RGBE_DATA_BLUE = 2,

            /* number of floats per pixel, use 4 since stored in rgba image format */
            //RGBE_DATA_SIZE = 4,

            /* flags indicating which fields in an rgbe_header_info are valid */
            RGBE_VALID_PROGRAMTYPE = 1,
            RGBE_VALID_FORMAT = 2,
            RGBE_VALID_DIMENSIONS = 4,

            NEWLINE = '\n',

            fgets = function ( buffer, lineLimit, consume ) {

                const chunkSize = 128;

                lineLimit = ! lineLimit ? 1024 : lineLimit;
                let p = buffer.pos,
                    i = - 1, len = 0, s = '',
                    chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );

                while ( ( 0 > ( i = chunk.indexOf( NEWLINE ) ) ) && ( len < lineLimit ) && ( p < buffer.byteLength ) ) {

                    s += chunk; len += chunk.length;
                    p += chunkSize;
                    chunk += String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );

                }

                if ( - 1 < i ) {

                    /*for (i=l-1; i>=0; i--) {
                        byteCode = m.charCodeAt(i);
                        if (byteCode > 0x7f && byteCode <= 0x7ff) byteLen++;
                        else if (byteCode > 0x7ff && byteCode <= 0xffff) byteLen += 2;
                        if (byteCode >= 0xDC00 && byteCode <= 0xDFFF) i--; //trail surrogate
                    }*/
                    if ( false !== consume ) buffer.pos += len + i + 1;
                    return s + chunk.slice( 0, i );

                }

                return false;

            },

            /* minimal header reading.  modify if you want to parse more information */
            RGBE_ReadHeader = function ( buffer ) {


                // regexes to parse header info fields
                const magic_token_re = /^#\?(\S+)/,
                    gamma_re = /^\s*GAMMA\s*=\s*(\d+(\.\d+)?)\s*$/,
                    exposure_re = /^\s*EXPOSURE\s*=\s*(\d+(\.\d+)?)\s*$/,
                    format_re = /^\s*FORMAT=(\S+)\s*$/,
                    dimensions_re = /^\s*\-Y\s+(\d+)\s+\+X\s+(\d+)\s*$/,

                    // RGBE format header struct
                    header = {

                        valid: 0, /* indicate which fields are valid */

                        string: '', /* the actual header string */

                        comments: '', /* comments found in header */

                        programtype: 'RGBE', /* listed at beginning of file to identify it after "#?". defaults to "RGBE" */

                        format: '', /* RGBE format, default 32-bit_rle_rgbe */

                        gamma: 1.0, /* image has already been gamma corrected with given gamma. defaults to 1.0 (no correction) */

                        exposure: 1.0, /* a value of 1.0 in an image corresponds to <exposure> watts/steradian/m^2. defaults to 1.0 */

                        width: 0, height: 0 /* image dimensions, width/height */

                    };

                let line, match;

                if ( buffer.pos >= buffer.byteLength || ! ( line = fgets( buffer ) ) ) {

                    rgbe_error( rgbe_read_error, 'no header found' );

                }

                /* if you want to require the magic token then uncomment the next line */
                if ( ! ( match = line.match( magic_token_re ) ) ) {

                    rgbe_error( rgbe_format_error, 'bad initial token' );

                }

                header.valid |= RGBE_VALID_PROGRAMTYPE;
                header.programtype = match[ 1 ];
                header.string += line + '\n';

                while ( true ) {

                    line = fgets( buffer );
                    if ( false === line ) break;
                    header.string += line + '\n';

                    if ( '#' === line.charAt( 0 ) ) {

                        header.comments += line + '\n';
                        continue; // comment line

                    }

                    if ( match = line.match( gamma_re ) ) {

                        header.gamma = parseFloat( match[ 1 ] );

                    }

                    if ( match = line.match( exposure_re ) ) {

                        header.exposure = parseFloat( match[ 1 ] );

                    }

                    if ( match = line.match( format_re ) ) {

                        header.valid |= RGBE_VALID_FORMAT;
                        header.format = match[ 1 ];//'32-bit_rle_rgbe';

                    }

                    if ( match = line.match( dimensions_re ) ) {

                        header.valid |= RGBE_VALID_DIMENSIONS;
                        header.height = parseInt( match[ 1 ], 10 );
                        header.width = parseInt( match[ 2 ], 10 );

                    }

                    if ( ( header.valid & RGBE_VALID_FORMAT ) && ( header.valid & RGBE_VALID_DIMENSIONS ) ) break;

                }

                if ( ! ( header.valid & RGBE_VALID_FORMAT ) ) {

                    rgbe_error( rgbe_format_error, 'missing format specifier' );

                }

                if ( ! ( header.valid & RGBE_VALID_DIMENSIONS ) ) {

                    rgbe_error( rgbe_format_error, 'missing image size specifier' );

                }

                return header;

            },

            RGBE_ReadPixels_RLE = function ( buffer, w, h ) {

                const scanline_width = w;

                if (
                    // run length encoding is not allowed so read flat
                    ( ( scanline_width < 8 ) || ( scanline_width > 0x7fff ) ) ||
                    // this file is not run length encoded
                    ( ( 2 !== buffer[ 0 ] ) || ( 2 !== buffer[ 1 ] ) || ( buffer[ 2 ] & 0x80 ) )
                ) {

                    // return the flat buffer
                    return new Uint8Array( buffer );

                }

                if ( scanline_width !== ( ( buffer[ 2 ] << 8 ) | buffer[ 3 ] ) ) {

                    rgbe_error( rgbe_format_error, 'wrong scanline width' );

                }

                const data_rgba = new Uint8Array( 4 * w * h );

                if ( ! data_rgba.length ) {

                    rgbe_error( rgbe_memory_error, 'unable to allocate buffer space' );

                }

                let offset = 0, pos = 0;

                const ptr_end = 4 * scanline_width;
                const rgbeStart = new Uint8Array( 4 );
                const scanline_buffer = new Uint8Array( ptr_end );
                let num_scanlines = h;

                // read in each successive scanline
                while ( ( num_scanlines > 0 ) && ( pos < buffer.byteLength ) ) {

                    if ( pos + 4 > buffer.byteLength ) {

                        rgbe_error( rgbe_read_error );

                    }

                    rgbeStart[ 0 ] = buffer[ pos ++ ];
                    rgbeStart[ 1 ] = buffer[ pos ++ ];
                    rgbeStart[ 2 ] = buffer[ pos ++ ];
                    rgbeStart[ 3 ] = buffer[ pos ++ ];

                    if ( ( 2 != rgbeStart[ 0 ] ) || ( 2 != rgbeStart[ 1 ] ) || ( ( ( rgbeStart[ 2 ] << 8 ) | rgbeStart[ 3 ] ) != scanline_width ) ) {

                        rgbe_error( rgbe_format_error, 'bad rgbe scanline format' );

                    }

                    // read each of the four channels for the scanline into the buffer
                    // first red, then green, then blue, then exponent
                    let ptr = 0, count;

                    while ( ( ptr < ptr_end ) && ( pos < buffer.byteLength ) ) {

                        count = buffer[ pos ++ ];
                        const isEncodedRun = count > 128;
                        if ( isEncodedRun ) count -= 128;

                        if ( ( 0 === count ) || ( ptr + count > ptr_end ) ) {

                            rgbe_error( rgbe_format_error, 'bad scanline data' );

                        }

                        if ( isEncodedRun ) {

                            // a (encoded) run of the same value
                            const byteValue = buffer[ pos ++ ];
                            for ( let i = 0; i < count; i ++ ) {

                                scanline_buffer[ ptr ++ ] = byteValue;

                            }
                            //ptr += count;

                        } else {

                            // a literal-run
                            scanline_buffer.set( buffer.subarray( pos, pos + count ), ptr );
                            ptr += count; pos += count;

                        }

                    }


                    // now convert data from buffer into rgba
                    // first red, then green, then blue, then exponent (alpha)
                    const l = scanline_width; //scanline_buffer.byteLength;
                    for ( let i = 0; i < l; i ++ ) {

                        let off = 0;
                        data_rgba[ offset ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 1 ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 2 ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 3 ] = scanline_buffer[ i + off ];
                        offset += 4;

                    }

                    num_scanlines --;

                }

                return data_rgba;

            };

        const RGBEByteToRGBFloat = function ( sourceArray, sourceOffset, destArray, destOffset ) {

            const e = sourceArray[ sourceOffset + 3 ];
            const scale = Math.pow( 2.0, e - 128.0 ) / 255.0;

            destArray[ destOffset + 0 ] = sourceArray[ sourceOffset + 0 ] * scale;
            destArray[ destOffset + 1 ] = sourceArray[ sourceOffset + 1 ] * scale;
            destArray[ destOffset + 2 ] = sourceArray[ sourceOffset + 2 ] * scale;
            destArray[ destOffset + 3 ] = 1;

        };

        const RGBEByteToRGBHalf = function ( sourceArray, sourceOffset, destArray, destOffset ) {

            const e = sourceArray[ sourceOffset + 3 ];
            const scale = Math.pow( 2.0, e - 128.0 ) / 255.0;

            // clamping to 65504, the maximum representable value in float16
            destArray[ destOffset + 0 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 0 ] * scale, 65504 ) );
            destArray[ destOffset + 1 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 1 ] * scale, 65504 ) );
            destArray[ destOffset + 2 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 2 ] * scale, 65504 ) );
            destArray[ destOffset + 3 ] = DataUtils.toHalfFloat( 1 );

        };

        const byteArray = new Uint8Array( buffer );
        byteArray.pos = 0;
        const rgbe_header_info = RGBE_ReadHeader( byteArray );

        const w = rgbe_header_info.width,
            h = rgbe_header_info.height,
            image_rgba_data = RGBE_ReadPixels_RLE( byteArray.subarray( byteArray.pos ), w, h );


        let data, type;
        let numElements;

        switch ( this.type ) {

            case FloatType:

                numElements = image_rgba_data.length / 4;
                const floatArray = new Float32Array( numElements * 4 );

                for ( let j = 0; j < numElements; j ++ ) {

                    RGBEByteToRGBFloat( image_rgba_data, j * 4, floatArray, j * 4 );

                }

                data = floatArray;
                type = FloatType;
                break;

            case HalfFloatType:

                numElements = image_rgba_data.length / 4;
                const halfArray = new Uint16Array( numElements * 4 );

                for ( let j = 0; j < numElements; j ++ ) {

                    RGBEByteToRGBHalf( image_rgba_data, j * 4, halfArray, j * 4 );

                }

                data = halfArray;
                type = HalfFloatType;
                break;

            default:

                throw new Error( 'THREE.RGBELoader: Unsupported type: ' + this.type );
                break;

        }

        return {
            width: w, height: h,
            data: data,
            header: rgbe_header_info.string,
            gamma: rgbe_header_info.gamma,
            exposure: rgbe_header_info.exposure,
            type: type
        };

    }

RGBELoader.setDataType(value: any): RGBELoader

JSDoc:

/**
     * Sets the texture type.
     *
     * @param {(HalfFloatType|FloatType)} value - The texture type to set.
     * @return {RGBELoader} A reference to this loader.
     */

Parameters:

  • value any

Returns: RGBELoader

Code
setDataType( value ) {

        this.type = value;
        return this;

    }

RGBELoader.load(url: any, onLoad: any, onProgress: any, onError: any): any

Parameters:

  • url any
  • onLoad any
  • onProgress any
  • onError any

Returns: any

Calls:

  • onLoad
  • super.load
Code
load( url, onLoad, onProgress, onError ) {

        function onLoadCallback( texture, texData ) {

            switch ( texture.type ) {

                case FloatType:
                case HalfFloatType:

                    texture.colorSpace = LinearSRGBColorSpace;
                    texture.minFilter = LinearFilter;
                    texture.magFilter = LinearFilter;
                    texture.generateMipmaps = false;
                    texture.flipY = true;

                    break;

            }

            if ( onLoad ) onLoad( texture, texData );

        }

        return super.load( url, onLoadCallback, onProgress, onError );

    }

rgbe_error(rgbe_error_code: any, msg: any): never

Parameters:

  • rgbe_error_code any
  • msg any

Returns: never

Code
function ( rgbe_error_code, msg ) {

                switch ( rgbe_error_code ) {

                    case rgbe_read_error: throw new Error( 'THREE.RGBELoader: Read Error: ' + ( msg || '' ) );
                    case rgbe_write_error: throw new Error( 'THREE.RGBELoader: Write Error: ' + ( msg || '' ) );
                    case rgbe_format_error: throw new Error( 'THREE.RGBELoader: Bad File Format: ' + ( msg || '' ) );
                    default:
                    case rgbe_memory_error: throw new Error( 'THREE.RGBELoader: Memory Error: ' + ( msg || '' ) );

                }

            }

fgets(buffer: any, lineLimit: any, consume: any): string | false

Parameters:

  • buffer any
  • lineLimit any
  • consume any

Returns: string | false

Calls:

  • String.fromCharCode.apply
  • buffer.subarray
  • chunk.indexOf
  • chunk.slice

Internal Comments:

/*for (i=l-1; i>=0; i--) {
                        byteCode = m.charCodeAt(i);
                        if (byteCode > 0x7f && byteCode <= 0x7ff) byteLen++;
                        else if (byteCode > 0x7ff && byteCode <= 0xffff) byteLen += 2;
                        if (byteCode >= 0xDC00 && byteCode <= 0xDFFF) i--; //trail surrogate
                    }*/

Code
function ( buffer, lineLimit, consume ) {

                const chunkSize = 128;

                lineLimit = ! lineLimit ? 1024 : lineLimit;
                let p = buffer.pos,
                    i = - 1, len = 0, s = '',
                    chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );

                while ( ( 0 > ( i = chunk.indexOf( NEWLINE ) ) ) && ( len < lineLimit ) && ( p < buffer.byteLength ) ) {

                    s += chunk; len += chunk.length;
                    p += chunkSize;
                    chunk += String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );

                }

                if ( - 1 < i ) {

                    /*for (i=l-1; i>=0; i--) {
                        byteCode = m.charCodeAt(i);
                        if (byteCode > 0x7f && byteCode <= 0x7ff) byteLen++;
                        else if (byteCode > 0x7ff && byteCode <= 0xffff) byteLen += 2;
                        if (byteCode >= 0xDC00 && byteCode <= 0xDFFF) i--; //trail surrogate
                    }*/
                    if ( false !== consume ) buffer.pos += len + i + 1;
                    return s + chunk.slice( 0, i );

                }

                return false;

            }

RGBE_ReadHeader(buffer: any): { valid: number; string: string; comments: string; programtype: string; format: string; gamma: number; exposure: number; width: number; height: number; }

Parameters:

  • buffer any

Returns: { valid: number; string: string; comments: string; programtype: string; format: string; gamma: number; exposure: number; width: number; height: number; }

Calls:

  • fgets
  • rgbe_error
  • line.match
  • line.charAt
  • parseFloat
  • parseInt

Internal Comments:

// regexes to parse header info fields (x2)
// RGBE format header struct (x2)
/* if you want to require the magic token then uncomment the next line */

Code
function ( buffer ) {


                // regexes to parse header info fields
                const magic_token_re = /^#\?(\S+)/,
                    gamma_re = /^\s*GAMMA\s*=\s*(\d+(\.\d+)?)\s*$/,
                    exposure_re = /^\s*EXPOSURE\s*=\s*(\d+(\.\d+)?)\s*$/,
                    format_re = /^\s*FORMAT=(\S+)\s*$/,
                    dimensions_re = /^\s*\-Y\s+(\d+)\s+\+X\s+(\d+)\s*$/,

                    // RGBE format header struct
                    header = {

                        valid: 0, /* indicate which fields are valid */

                        string: '', /* the actual header string */

                        comments: '', /* comments found in header */

                        programtype: 'RGBE', /* listed at beginning of file to identify it after "#?". defaults to "RGBE" */

                        format: '', /* RGBE format, default 32-bit_rle_rgbe */

                        gamma: 1.0, /* image has already been gamma corrected with given gamma. defaults to 1.0 (no correction) */

                        exposure: 1.0, /* a value of 1.0 in an image corresponds to <exposure> watts/steradian/m^2. defaults to 1.0 */

                        width: 0, height: 0 /* image dimensions, width/height */

                    };

                let line, match;

                if ( buffer.pos >= buffer.byteLength || ! ( line = fgets( buffer ) ) ) {

                    rgbe_error( rgbe_read_error, 'no header found' );

                }

                /* if you want to require the magic token then uncomment the next line */
                if ( ! ( match = line.match( magic_token_re ) ) ) {

                    rgbe_error( rgbe_format_error, 'bad initial token' );

                }

                header.valid |= RGBE_VALID_PROGRAMTYPE;
                header.programtype = match[ 1 ];
                header.string += line + '\n';

                while ( true ) {

                    line = fgets( buffer );
                    if ( false === line ) break;
                    header.string += line + '\n';

                    if ( '#' === line.charAt( 0 ) ) {

                        header.comments += line + '\n';
                        continue; // comment line

                    }

                    if ( match = line.match( gamma_re ) ) {

                        header.gamma = parseFloat( match[ 1 ] );

                    }

                    if ( match = line.match( exposure_re ) ) {

                        header.exposure = parseFloat( match[ 1 ] );

                    }

                    if ( match = line.match( format_re ) ) {

                        header.valid |= RGBE_VALID_FORMAT;
                        header.format = match[ 1 ];//'32-bit_rle_rgbe';

                    }

                    if ( match = line.match( dimensions_re ) ) {

                        header.valid |= RGBE_VALID_DIMENSIONS;
                        header.height = parseInt( match[ 1 ], 10 );
                        header.width = parseInt( match[ 2 ], 10 );

                    }

                    if ( ( header.valid & RGBE_VALID_FORMAT ) && ( header.valid & RGBE_VALID_DIMENSIONS ) ) break;

                }

                if ( ! ( header.valid & RGBE_VALID_FORMAT ) ) {

                    rgbe_error( rgbe_format_error, 'missing format specifier' );

                }

                if ( ! ( header.valid & RGBE_VALID_DIMENSIONS ) ) {

                    rgbe_error( rgbe_format_error, 'missing image size specifier' );

                }

                return header;

            }

RGBE_ReadPixels_RLE(buffer: any, w: any, h: any): Uint8Array<any>

Parameters:

  • buffer any
  • w any
  • h any

Returns: Uint8Array<any>

Calls:

  • rgbe_error
  • scanline_buffer.set
  • buffer.subarray

Internal Comments:

// run length encoding is not allowed so read flat (x2)
// this file is not run length encoded
// return the flat buffer
// read in each successive scanline
// read each of the four channels for the scanline into the buffer (x2)
// first red, then green, then blue, then exponent (x2)
// a (encoded) run of the same value (x2)
// a literal-run (x4)
// now convert data from buffer into rgba (x2)
// first red, then green, then blue, then exponent (alpha) (x2)

Code
function ( buffer, w, h ) {

                const scanline_width = w;

                if (
                    // run length encoding is not allowed so read flat
                    ( ( scanline_width < 8 ) || ( scanline_width > 0x7fff ) ) ||
                    // this file is not run length encoded
                    ( ( 2 !== buffer[ 0 ] ) || ( 2 !== buffer[ 1 ] ) || ( buffer[ 2 ] & 0x80 ) )
                ) {

                    // return the flat buffer
                    return new Uint8Array( buffer );

                }

                if ( scanline_width !== ( ( buffer[ 2 ] << 8 ) | buffer[ 3 ] ) ) {

                    rgbe_error( rgbe_format_error, 'wrong scanline width' );

                }

                const data_rgba = new Uint8Array( 4 * w * h );

                if ( ! data_rgba.length ) {

                    rgbe_error( rgbe_memory_error, 'unable to allocate buffer space' );

                }

                let offset = 0, pos = 0;

                const ptr_end = 4 * scanline_width;
                const rgbeStart = new Uint8Array( 4 );
                const scanline_buffer = new Uint8Array( ptr_end );
                let num_scanlines = h;

                // read in each successive scanline
                while ( ( num_scanlines > 0 ) && ( pos < buffer.byteLength ) ) {

                    if ( pos + 4 > buffer.byteLength ) {

                        rgbe_error( rgbe_read_error );

                    }

                    rgbeStart[ 0 ] = buffer[ pos ++ ];
                    rgbeStart[ 1 ] = buffer[ pos ++ ];
                    rgbeStart[ 2 ] = buffer[ pos ++ ];
                    rgbeStart[ 3 ] = buffer[ pos ++ ];

                    if ( ( 2 != rgbeStart[ 0 ] ) || ( 2 != rgbeStart[ 1 ] ) || ( ( ( rgbeStart[ 2 ] << 8 ) | rgbeStart[ 3 ] ) != scanline_width ) ) {

                        rgbe_error( rgbe_format_error, 'bad rgbe scanline format' );

                    }

                    // read each of the four channels for the scanline into the buffer
                    // first red, then green, then blue, then exponent
                    let ptr = 0, count;

                    while ( ( ptr < ptr_end ) && ( pos < buffer.byteLength ) ) {

                        count = buffer[ pos ++ ];
                        const isEncodedRun = count > 128;
                        if ( isEncodedRun ) count -= 128;

                        if ( ( 0 === count ) || ( ptr + count > ptr_end ) ) {

                            rgbe_error( rgbe_format_error, 'bad scanline data' );

                        }

                        if ( isEncodedRun ) {

                            // a (encoded) run of the same value
                            const byteValue = buffer[ pos ++ ];
                            for ( let i = 0; i < count; i ++ ) {

                                scanline_buffer[ ptr ++ ] = byteValue;

                            }
                            //ptr += count;

                        } else {

                            // a literal-run
                            scanline_buffer.set( buffer.subarray( pos, pos + count ), ptr );
                            ptr += count; pos += count;

                        }

                    }


                    // now convert data from buffer into rgba
                    // first red, then green, then blue, then exponent (alpha)
                    const l = scanline_width; //scanline_buffer.byteLength;
                    for ( let i = 0; i < l; i ++ ) {

                        let off = 0;
                        data_rgba[ offset ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 1 ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 2 ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 3 ] = scanline_buffer[ i + off ];
                        offset += 4;

                    }

                    num_scanlines --;

                }

                return data_rgba;

            }

RGBEByteToRGBFloat(sourceArray: any, sourceOffset: any, destArray: any, destOffset: any): void

Parameters:

  • sourceArray any
  • sourceOffset any
  • destArray any
  • destOffset any

Returns: void

Calls:

  • Math.pow
Code
function ( sourceArray, sourceOffset, destArray, destOffset ) {

            const e = sourceArray[ sourceOffset + 3 ];
            const scale = Math.pow( 2.0, e - 128.0 ) / 255.0;

            destArray[ destOffset + 0 ] = sourceArray[ sourceOffset + 0 ] * scale;
            destArray[ destOffset + 1 ] = sourceArray[ sourceOffset + 1 ] * scale;
            destArray[ destOffset + 2 ] = sourceArray[ sourceOffset + 2 ] * scale;
            destArray[ destOffset + 3 ] = 1;

        }

RGBEByteToRGBHalf(sourceArray: any, sourceOffset: any, destArray: any, destOffset: any): void

Parameters:

  • sourceArray any
  • sourceOffset any
  • destArray any
  • destOffset any

Returns: void

Calls:

  • Math.pow
  • DataUtils.toHalfFloat
  • Math.min

Internal Comments:

// clamping to 65504, the maximum representable value in float16 (x4)

Code
function ( sourceArray, sourceOffset, destArray, destOffset ) {

            const e = sourceArray[ sourceOffset + 3 ];
            const scale = Math.pow( 2.0, e - 128.0 ) / 255.0;

            // clamping to 65504, the maximum representable value in float16
            destArray[ destOffset + 0 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 0 ] * scale, 65504 ) );
            destArray[ destOffset + 1 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 1 ] * scale, 65504 ) );
            destArray[ destOffset + 2 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 2 ] * scale, 65504 ) );
            destArray[ destOffset + 3 ] = DataUtils.toHalfFloat( 1 );

        }

onLoadCallback(texture: any, texData: any): void

Parameters:

  • texture any
  • texData any

Returns: void

Calls:

  • onLoad
Code
function onLoadCallback( texture, texData ) {

            switch ( texture.type ) {

                case FloatType:
                case HalfFloatType:

                    texture.colorSpace = LinearSRGBColorSpace;
                    texture.minFilter = LinearFilter;
                    texture.magFilter = LinearFilter;
                    texture.generateMipmaps = false;
                    texture.flipY = true;

                    break;

            }

            if ( onLoad ) onLoad( texture, texData );

        }

Classes

RGBELoader

Class Code
class RGBELoader extends DataTextureLoader {

    /**
     * Constructs a new RGBE loader.
     *
     * @param {LoadingManager} [manager] - The loading manager.
     */
    constructor( manager ) {

        super( manager );

        /**
         * The texture type.
         *
         * @type {(HalfFloatType|FloatType)}
         * @default HalfFloatType
         */
        this.type = HalfFloatType;

    }

    /**
     * Parses the given RGBE texture data.
     *
     * @param {ArrayBuffer} buffer - The raw texture data.
     * @return {DataTextureLoader~TexData} An object representing the parsed texture data.
     */
    parse( buffer ) {

        // adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html

        const
            /* default error routine.  change this to change error handling */
            rgbe_read_error = 1,
            rgbe_write_error = 2,
            rgbe_format_error = 3,
            rgbe_memory_error = 4,
            rgbe_error = function ( rgbe_error_code, msg ) {

                switch ( rgbe_error_code ) {

                    case rgbe_read_error: throw new Error( 'THREE.RGBELoader: Read Error: ' + ( msg || '' ) );
                    case rgbe_write_error: throw new Error( 'THREE.RGBELoader: Write Error: ' + ( msg || '' ) );
                    case rgbe_format_error: throw new Error( 'THREE.RGBELoader: Bad File Format: ' + ( msg || '' ) );
                    default:
                    case rgbe_memory_error: throw new Error( 'THREE.RGBELoader: Memory Error: ' + ( msg || '' ) );

                }

            },

            /* offsets to red, green, and blue components in a data (float) pixel */
            //RGBE_DATA_RED = 0,
            //RGBE_DATA_GREEN = 1,
            //RGBE_DATA_BLUE = 2,

            /* number of floats per pixel, use 4 since stored in rgba image format */
            //RGBE_DATA_SIZE = 4,

            /* flags indicating which fields in an rgbe_header_info are valid */
            RGBE_VALID_PROGRAMTYPE = 1,
            RGBE_VALID_FORMAT = 2,
            RGBE_VALID_DIMENSIONS = 4,

            NEWLINE = '\n',

            fgets = function ( buffer, lineLimit, consume ) {

                const chunkSize = 128;

                lineLimit = ! lineLimit ? 1024 : lineLimit;
                let p = buffer.pos,
                    i = - 1, len = 0, s = '',
                    chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );

                while ( ( 0 > ( i = chunk.indexOf( NEWLINE ) ) ) && ( len < lineLimit ) && ( p < buffer.byteLength ) ) {

                    s += chunk; len += chunk.length;
                    p += chunkSize;
                    chunk += String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );

                }

                if ( - 1 < i ) {

                    /*for (i=l-1; i>=0; i--) {
                        byteCode = m.charCodeAt(i);
                        if (byteCode > 0x7f && byteCode <= 0x7ff) byteLen++;
                        else if (byteCode > 0x7ff && byteCode <= 0xffff) byteLen += 2;
                        if (byteCode >= 0xDC00 && byteCode <= 0xDFFF) i--; //trail surrogate
                    }*/
                    if ( false !== consume ) buffer.pos += len + i + 1;
                    return s + chunk.slice( 0, i );

                }

                return false;

            },

            /* minimal header reading.  modify if you want to parse more information */
            RGBE_ReadHeader = function ( buffer ) {


                // regexes to parse header info fields
                const magic_token_re = /^#\?(\S+)/,
                    gamma_re = /^\s*GAMMA\s*=\s*(\d+(\.\d+)?)\s*$/,
                    exposure_re = /^\s*EXPOSURE\s*=\s*(\d+(\.\d+)?)\s*$/,
                    format_re = /^\s*FORMAT=(\S+)\s*$/,
                    dimensions_re = /^\s*\-Y\s+(\d+)\s+\+X\s+(\d+)\s*$/,

                    // RGBE format header struct
                    header = {

                        valid: 0, /* indicate which fields are valid */

                        string: '', /* the actual header string */

                        comments: '', /* comments found in header */

                        programtype: 'RGBE', /* listed at beginning of file to identify it after "#?". defaults to "RGBE" */

                        format: '', /* RGBE format, default 32-bit_rle_rgbe */

                        gamma: 1.0, /* image has already been gamma corrected with given gamma. defaults to 1.0 (no correction) */

                        exposure: 1.0, /* a value of 1.0 in an image corresponds to <exposure> watts/steradian/m^2. defaults to 1.0 */

                        width: 0, height: 0 /* image dimensions, width/height */

                    };

                let line, match;

                if ( buffer.pos >= buffer.byteLength || ! ( line = fgets( buffer ) ) ) {

                    rgbe_error( rgbe_read_error, 'no header found' );

                }

                /* if you want to require the magic token then uncomment the next line */
                if ( ! ( match = line.match( magic_token_re ) ) ) {

                    rgbe_error( rgbe_format_error, 'bad initial token' );

                }

                header.valid |= RGBE_VALID_PROGRAMTYPE;
                header.programtype = match[ 1 ];
                header.string += line + '\n';

                while ( true ) {

                    line = fgets( buffer );
                    if ( false === line ) break;
                    header.string += line + '\n';

                    if ( '#' === line.charAt( 0 ) ) {

                        header.comments += line + '\n';
                        continue; // comment line

                    }

                    if ( match = line.match( gamma_re ) ) {

                        header.gamma = parseFloat( match[ 1 ] );

                    }

                    if ( match = line.match( exposure_re ) ) {

                        header.exposure = parseFloat( match[ 1 ] );

                    }

                    if ( match = line.match( format_re ) ) {

                        header.valid |= RGBE_VALID_FORMAT;
                        header.format = match[ 1 ];//'32-bit_rle_rgbe';

                    }

                    if ( match = line.match( dimensions_re ) ) {

                        header.valid |= RGBE_VALID_DIMENSIONS;
                        header.height = parseInt( match[ 1 ], 10 );
                        header.width = parseInt( match[ 2 ], 10 );

                    }

                    if ( ( header.valid & RGBE_VALID_FORMAT ) && ( header.valid & RGBE_VALID_DIMENSIONS ) ) break;

                }

                if ( ! ( header.valid & RGBE_VALID_FORMAT ) ) {

                    rgbe_error( rgbe_format_error, 'missing format specifier' );

                }

                if ( ! ( header.valid & RGBE_VALID_DIMENSIONS ) ) {

                    rgbe_error( rgbe_format_error, 'missing image size specifier' );

                }

                return header;

            },

            RGBE_ReadPixels_RLE = function ( buffer, w, h ) {

                const scanline_width = w;

                if (
                    // run length encoding is not allowed so read flat
                    ( ( scanline_width < 8 ) || ( scanline_width > 0x7fff ) ) ||
                    // this file is not run length encoded
                    ( ( 2 !== buffer[ 0 ] ) || ( 2 !== buffer[ 1 ] ) || ( buffer[ 2 ] & 0x80 ) )
                ) {

                    // return the flat buffer
                    return new Uint8Array( buffer );

                }

                if ( scanline_width !== ( ( buffer[ 2 ] << 8 ) | buffer[ 3 ] ) ) {

                    rgbe_error( rgbe_format_error, 'wrong scanline width' );

                }

                const data_rgba = new Uint8Array( 4 * w * h );

                if ( ! data_rgba.length ) {

                    rgbe_error( rgbe_memory_error, 'unable to allocate buffer space' );

                }

                let offset = 0, pos = 0;

                const ptr_end = 4 * scanline_width;
                const rgbeStart = new Uint8Array( 4 );
                const scanline_buffer = new Uint8Array( ptr_end );
                let num_scanlines = h;

                // read in each successive scanline
                while ( ( num_scanlines > 0 ) && ( pos < buffer.byteLength ) ) {

                    if ( pos + 4 > buffer.byteLength ) {

                        rgbe_error( rgbe_read_error );

                    }

                    rgbeStart[ 0 ] = buffer[ pos ++ ];
                    rgbeStart[ 1 ] = buffer[ pos ++ ];
                    rgbeStart[ 2 ] = buffer[ pos ++ ];
                    rgbeStart[ 3 ] = buffer[ pos ++ ];

                    if ( ( 2 != rgbeStart[ 0 ] ) || ( 2 != rgbeStart[ 1 ] ) || ( ( ( rgbeStart[ 2 ] << 8 ) | rgbeStart[ 3 ] ) != scanline_width ) ) {

                        rgbe_error( rgbe_format_error, 'bad rgbe scanline format' );

                    }

                    // read each of the four channels for the scanline into the buffer
                    // first red, then green, then blue, then exponent
                    let ptr = 0, count;

                    while ( ( ptr < ptr_end ) && ( pos < buffer.byteLength ) ) {

                        count = buffer[ pos ++ ];
                        const isEncodedRun = count > 128;
                        if ( isEncodedRun ) count -= 128;

                        if ( ( 0 === count ) || ( ptr + count > ptr_end ) ) {

                            rgbe_error( rgbe_format_error, 'bad scanline data' );

                        }

                        if ( isEncodedRun ) {

                            // a (encoded) run of the same value
                            const byteValue = buffer[ pos ++ ];
                            for ( let i = 0; i < count; i ++ ) {

                                scanline_buffer[ ptr ++ ] = byteValue;

                            }
                            //ptr += count;

                        } else {

                            // a literal-run
                            scanline_buffer.set( buffer.subarray( pos, pos + count ), ptr );
                            ptr += count; pos += count;

                        }

                    }


                    // now convert data from buffer into rgba
                    // first red, then green, then blue, then exponent (alpha)
                    const l = scanline_width; //scanline_buffer.byteLength;
                    for ( let i = 0; i < l; i ++ ) {

                        let off = 0;
                        data_rgba[ offset ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 1 ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 2 ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 3 ] = scanline_buffer[ i + off ];
                        offset += 4;

                    }

                    num_scanlines --;

                }

                return data_rgba;

            };

        const RGBEByteToRGBFloat = function ( sourceArray, sourceOffset, destArray, destOffset ) {

            const e = sourceArray[ sourceOffset + 3 ];
            const scale = Math.pow( 2.0, e - 128.0 ) / 255.0;

            destArray[ destOffset + 0 ] = sourceArray[ sourceOffset + 0 ] * scale;
            destArray[ destOffset + 1 ] = sourceArray[ sourceOffset + 1 ] * scale;
            destArray[ destOffset + 2 ] = sourceArray[ sourceOffset + 2 ] * scale;
            destArray[ destOffset + 3 ] = 1;

        };

        const RGBEByteToRGBHalf = function ( sourceArray, sourceOffset, destArray, destOffset ) {

            const e = sourceArray[ sourceOffset + 3 ];
            const scale = Math.pow( 2.0, e - 128.0 ) / 255.0;

            // clamping to 65504, the maximum representable value in float16
            destArray[ destOffset + 0 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 0 ] * scale, 65504 ) );
            destArray[ destOffset + 1 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 1 ] * scale, 65504 ) );
            destArray[ destOffset + 2 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 2 ] * scale, 65504 ) );
            destArray[ destOffset + 3 ] = DataUtils.toHalfFloat( 1 );

        };

        const byteArray = new Uint8Array( buffer );
        byteArray.pos = 0;
        const rgbe_header_info = RGBE_ReadHeader( byteArray );

        const w = rgbe_header_info.width,
            h = rgbe_header_info.height,
            image_rgba_data = RGBE_ReadPixels_RLE( byteArray.subarray( byteArray.pos ), w, h );


        let data, type;
        let numElements;

        switch ( this.type ) {

            case FloatType:

                numElements = image_rgba_data.length / 4;
                const floatArray = new Float32Array( numElements * 4 );

                for ( let j = 0; j < numElements; j ++ ) {

                    RGBEByteToRGBFloat( image_rgba_data, j * 4, floatArray, j * 4 );

                }

                data = floatArray;
                type = FloatType;
                break;

            case HalfFloatType:

                numElements = image_rgba_data.length / 4;
                const halfArray = new Uint16Array( numElements * 4 );

                for ( let j = 0; j < numElements; j ++ ) {

                    RGBEByteToRGBHalf( image_rgba_data, j * 4, halfArray, j * 4 );

                }

                data = halfArray;
                type = HalfFloatType;
                break;

            default:

                throw new Error( 'THREE.RGBELoader: Unsupported type: ' + this.type );
                break;

        }

        return {
            width: w, height: h,
            data: data,
            header: rgbe_header_info.string,
            gamma: rgbe_header_info.gamma,
            exposure: rgbe_header_info.exposure,
            type: type
        };

    }

    /**
     * Sets the texture type.
     *
     * @param {(HalfFloatType|FloatType)} value - The texture type to set.
     * @return {RGBELoader} A reference to this loader.
     */
    setDataType( value ) {

        this.type = value;
        return this;

    }

    load( url, onLoad, onProgress, onError ) {

        function onLoadCallback( texture, texData ) {

            switch ( texture.type ) {

                case FloatType:
                case HalfFloatType:

                    texture.colorSpace = LinearSRGBColorSpace;
                    texture.minFilter = LinearFilter;
                    texture.magFilter = LinearFilter;
                    texture.generateMipmaps = false;
                    texture.flipY = true;

                    break;

            }

            if ( onLoad ) onLoad( texture, texData );

        }

        return super.load( url, onLoadCallback, onProgress, onError );

    }

}

Methods

parse(buffer: ArrayBuffer): DataTextureLoader
Code
parse( buffer ) {

        // adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html

        const
            /* default error routine.  change this to change error handling */
            rgbe_read_error = 1,
            rgbe_write_error = 2,
            rgbe_format_error = 3,
            rgbe_memory_error = 4,
            rgbe_error = function ( rgbe_error_code, msg ) {

                switch ( rgbe_error_code ) {

                    case rgbe_read_error: throw new Error( 'THREE.RGBELoader: Read Error: ' + ( msg || '' ) );
                    case rgbe_write_error: throw new Error( 'THREE.RGBELoader: Write Error: ' + ( msg || '' ) );
                    case rgbe_format_error: throw new Error( 'THREE.RGBELoader: Bad File Format: ' + ( msg || '' ) );
                    default:
                    case rgbe_memory_error: throw new Error( 'THREE.RGBELoader: Memory Error: ' + ( msg || '' ) );

                }

            },

            /* offsets to red, green, and blue components in a data (float) pixel */
            //RGBE_DATA_RED = 0,
            //RGBE_DATA_GREEN = 1,
            //RGBE_DATA_BLUE = 2,

            /* number of floats per pixel, use 4 since stored in rgba image format */
            //RGBE_DATA_SIZE = 4,

            /* flags indicating which fields in an rgbe_header_info are valid */
            RGBE_VALID_PROGRAMTYPE = 1,
            RGBE_VALID_FORMAT = 2,
            RGBE_VALID_DIMENSIONS = 4,

            NEWLINE = '\n',

            fgets = function ( buffer, lineLimit, consume ) {

                const chunkSize = 128;

                lineLimit = ! lineLimit ? 1024 : lineLimit;
                let p = buffer.pos,
                    i = - 1, len = 0, s = '',
                    chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );

                while ( ( 0 > ( i = chunk.indexOf( NEWLINE ) ) ) && ( len < lineLimit ) && ( p < buffer.byteLength ) ) {

                    s += chunk; len += chunk.length;
                    p += chunkSize;
                    chunk += String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );

                }

                if ( - 1 < i ) {

                    /*for (i=l-1; i>=0; i--) {
                        byteCode = m.charCodeAt(i);
                        if (byteCode > 0x7f && byteCode <= 0x7ff) byteLen++;
                        else if (byteCode > 0x7ff && byteCode <= 0xffff) byteLen += 2;
                        if (byteCode >= 0xDC00 && byteCode <= 0xDFFF) i--; //trail surrogate
                    }*/
                    if ( false !== consume ) buffer.pos += len + i + 1;
                    return s + chunk.slice( 0, i );

                }

                return false;

            },

            /* minimal header reading.  modify if you want to parse more information */
            RGBE_ReadHeader = function ( buffer ) {


                // regexes to parse header info fields
                const magic_token_re = /^#\?(\S+)/,
                    gamma_re = /^\s*GAMMA\s*=\s*(\d+(\.\d+)?)\s*$/,
                    exposure_re = /^\s*EXPOSURE\s*=\s*(\d+(\.\d+)?)\s*$/,
                    format_re = /^\s*FORMAT=(\S+)\s*$/,
                    dimensions_re = /^\s*\-Y\s+(\d+)\s+\+X\s+(\d+)\s*$/,

                    // RGBE format header struct
                    header = {

                        valid: 0, /* indicate which fields are valid */

                        string: '', /* the actual header string */

                        comments: '', /* comments found in header */

                        programtype: 'RGBE', /* listed at beginning of file to identify it after "#?". defaults to "RGBE" */

                        format: '', /* RGBE format, default 32-bit_rle_rgbe */

                        gamma: 1.0, /* image has already been gamma corrected with given gamma. defaults to 1.0 (no correction) */

                        exposure: 1.0, /* a value of 1.0 in an image corresponds to <exposure> watts/steradian/m^2. defaults to 1.0 */

                        width: 0, height: 0 /* image dimensions, width/height */

                    };

                let line, match;

                if ( buffer.pos >= buffer.byteLength || ! ( line = fgets( buffer ) ) ) {

                    rgbe_error( rgbe_read_error, 'no header found' );

                }

                /* if you want to require the magic token then uncomment the next line */
                if ( ! ( match = line.match( magic_token_re ) ) ) {

                    rgbe_error( rgbe_format_error, 'bad initial token' );

                }

                header.valid |= RGBE_VALID_PROGRAMTYPE;
                header.programtype = match[ 1 ];
                header.string += line + '\n';

                while ( true ) {

                    line = fgets( buffer );
                    if ( false === line ) break;
                    header.string += line + '\n';

                    if ( '#' === line.charAt( 0 ) ) {

                        header.comments += line + '\n';
                        continue; // comment line

                    }

                    if ( match = line.match( gamma_re ) ) {

                        header.gamma = parseFloat( match[ 1 ] );

                    }

                    if ( match = line.match( exposure_re ) ) {

                        header.exposure = parseFloat( match[ 1 ] );

                    }

                    if ( match = line.match( format_re ) ) {

                        header.valid |= RGBE_VALID_FORMAT;
                        header.format = match[ 1 ];//'32-bit_rle_rgbe';

                    }

                    if ( match = line.match( dimensions_re ) ) {

                        header.valid |= RGBE_VALID_DIMENSIONS;
                        header.height = parseInt( match[ 1 ], 10 );
                        header.width = parseInt( match[ 2 ], 10 );

                    }

                    if ( ( header.valid & RGBE_VALID_FORMAT ) && ( header.valid & RGBE_VALID_DIMENSIONS ) ) break;

                }

                if ( ! ( header.valid & RGBE_VALID_FORMAT ) ) {

                    rgbe_error( rgbe_format_error, 'missing format specifier' );

                }

                if ( ! ( header.valid & RGBE_VALID_DIMENSIONS ) ) {

                    rgbe_error( rgbe_format_error, 'missing image size specifier' );

                }

                return header;

            },

            RGBE_ReadPixels_RLE = function ( buffer, w, h ) {

                const scanline_width = w;

                if (
                    // run length encoding is not allowed so read flat
                    ( ( scanline_width < 8 ) || ( scanline_width > 0x7fff ) ) ||
                    // this file is not run length encoded
                    ( ( 2 !== buffer[ 0 ] ) || ( 2 !== buffer[ 1 ] ) || ( buffer[ 2 ] & 0x80 ) )
                ) {

                    // return the flat buffer
                    return new Uint8Array( buffer );

                }

                if ( scanline_width !== ( ( buffer[ 2 ] << 8 ) | buffer[ 3 ] ) ) {

                    rgbe_error( rgbe_format_error, 'wrong scanline width' );

                }

                const data_rgba = new Uint8Array( 4 * w * h );

                if ( ! data_rgba.length ) {

                    rgbe_error( rgbe_memory_error, 'unable to allocate buffer space' );

                }

                let offset = 0, pos = 0;

                const ptr_end = 4 * scanline_width;
                const rgbeStart = new Uint8Array( 4 );
                const scanline_buffer = new Uint8Array( ptr_end );
                let num_scanlines = h;

                // read in each successive scanline
                while ( ( num_scanlines > 0 ) && ( pos < buffer.byteLength ) ) {

                    if ( pos + 4 > buffer.byteLength ) {

                        rgbe_error( rgbe_read_error );

                    }

                    rgbeStart[ 0 ] = buffer[ pos ++ ];
                    rgbeStart[ 1 ] = buffer[ pos ++ ];
                    rgbeStart[ 2 ] = buffer[ pos ++ ];
                    rgbeStart[ 3 ] = buffer[ pos ++ ];

                    if ( ( 2 != rgbeStart[ 0 ] ) || ( 2 != rgbeStart[ 1 ] ) || ( ( ( rgbeStart[ 2 ] << 8 ) | rgbeStart[ 3 ] ) != scanline_width ) ) {

                        rgbe_error( rgbe_format_error, 'bad rgbe scanline format' );

                    }

                    // read each of the four channels for the scanline into the buffer
                    // first red, then green, then blue, then exponent
                    let ptr = 0, count;

                    while ( ( ptr < ptr_end ) && ( pos < buffer.byteLength ) ) {

                        count = buffer[ pos ++ ];
                        const isEncodedRun = count > 128;
                        if ( isEncodedRun ) count -= 128;

                        if ( ( 0 === count ) || ( ptr + count > ptr_end ) ) {

                            rgbe_error( rgbe_format_error, 'bad scanline data' );

                        }

                        if ( isEncodedRun ) {

                            // a (encoded) run of the same value
                            const byteValue = buffer[ pos ++ ];
                            for ( let i = 0; i < count; i ++ ) {

                                scanline_buffer[ ptr ++ ] = byteValue;

                            }
                            //ptr += count;

                        } else {

                            // a literal-run
                            scanline_buffer.set( buffer.subarray( pos, pos + count ), ptr );
                            ptr += count; pos += count;

                        }

                    }


                    // now convert data from buffer into rgba
                    // first red, then green, then blue, then exponent (alpha)
                    const l = scanline_width; //scanline_buffer.byteLength;
                    for ( let i = 0; i < l; i ++ ) {

                        let off = 0;
                        data_rgba[ offset ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 1 ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 2 ] = scanline_buffer[ i + off ];
                        off += scanline_width; //1;
                        data_rgba[ offset + 3 ] = scanline_buffer[ i + off ];
                        offset += 4;

                    }

                    num_scanlines --;

                }

                return data_rgba;

            };

        const RGBEByteToRGBFloat = function ( sourceArray, sourceOffset, destArray, destOffset ) {

            const e = sourceArray[ sourceOffset + 3 ];
            const scale = Math.pow( 2.0, e - 128.0 ) / 255.0;

            destArray[ destOffset + 0 ] = sourceArray[ sourceOffset + 0 ] * scale;
            destArray[ destOffset + 1 ] = sourceArray[ sourceOffset + 1 ] * scale;
            destArray[ destOffset + 2 ] = sourceArray[ sourceOffset + 2 ] * scale;
            destArray[ destOffset + 3 ] = 1;

        };

        const RGBEByteToRGBHalf = function ( sourceArray, sourceOffset, destArray, destOffset ) {

            const e = sourceArray[ sourceOffset + 3 ];
            const scale = Math.pow( 2.0, e - 128.0 ) / 255.0;

            // clamping to 65504, the maximum representable value in float16
            destArray[ destOffset + 0 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 0 ] * scale, 65504 ) );
            destArray[ destOffset + 1 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 1 ] * scale, 65504 ) );
            destArray[ destOffset + 2 ] = DataUtils.toHalfFloat( Math.min( sourceArray[ sourceOffset + 2 ] * scale, 65504 ) );
            destArray[ destOffset + 3 ] = DataUtils.toHalfFloat( 1 );

        };

        const byteArray = new Uint8Array( buffer );
        byteArray.pos = 0;
        const rgbe_header_info = RGBE_ReadHeader( byteArray );

        const w = rgbe_header_info.width,
            h = rgbe_header_info.height,
            image_rgba_data = RGBE_ReadPixels_RLE( byteArray.subarray( byteArray.pos ), w, h );


        let data, type;
        let numElements;

        switch ( this.type ) {

            case FloatType:

                numElements = image_rgba_data.length / 4;
                const floatArray = new Float32Array( numElements * 4 );

                for ( let j = 0; j < numElements; j ++ ) {

                    RGBEByteToRGBFloat( image_rgba_data, j * 4, floatArray, j * 4 );

                }

                data = floatArray;
                type = FloatType;
                break;

            case HalfFloatType:

                numElements = image_rgba_data.length / 4;
                const halfArray = new Uint16Array( numElements * 4 );

                for ( let j = 0; j < numElements; j ++ ) {

                    RGBEByteToRGBHalf( image_rgba_data, j * 4, halfArray, j * 4 );

                }

                data = halfArray;
                type = HalfFloatType;
                break;

            default:

                throw new Error( 'THREE.RGBELoader: Unsupported type: ' + this.type );
                break;

        }

        return {
            width: w, height: h,
            data: data,
            header: rgbe_header_info.string,
            gamma: rgbe_header_info.gamma,
            exposure: rgbe_header_info.exposure,
            type: type
        };

    }
setDataType(value: any): RGBELoader
Code
setDataType( value ) {

        this.type = value;
        return this;

    }
load(url: any, onLoad: any, onProgress: any, onError: any): any
Code
load( url, onLoad, onProgress, onError ) {

        function onLoadCallback( texture, texData ) {

            switch ( texture.type ) {

                case FloatType:
                case HalfFloatType:

                    texture.colorSpace = LinearSRGBColorSpace;
                    texture.minFilter = LinearFilter;
                    texture.magFilter = LinearFilter;
                    texture.generateMipmaps = false;
                    texture.flipY = true;

                    break;

            }

            if ( onLoad ) onLoad( texture, texData );

        }

        return super.load( url, onLoadCallback, onProgress, onError );

    }