EXRLoader.js 27.4 KB
Newer Older
R
Richard Monette 已提交
1 2
/**
 * @author Richard M. / https://github.com/richardmonette
R
Richard Monette 已提交
3 4 5 6 7 8
 *
 * OpenEXR loader which, currently, supports reading 16 bit half data, in either
 * uncompressed or PIZ wavelet compressed form.
 *
 * Referred to the original Industrial Light & Magic OpenEXR implementation and the TinyEXR / Syoyo Fujita
 * implementation, so I have preserved their copyright notices.
R
Richard Monette 已提交
9 10
 */

R
Richard Monette 已提交
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
// /*
// Copyright (c) 2014 - 2017, Syoyo Fujita
// All rights reserved.

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the Syoyo Fujita nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.

// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// */

// // TinyEXR contains some OpenEXR code, which is licensed under ------------

// ///////////////////////////////////////////////////////////////////////////
// //
// // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// // Digital Ltd. LLC
// //
// // All rights reserved.
// //
// // Redistribution and use in source and binary forms, with or without
// // modification, are permitted provided that the following conditions are
// // met:
// // *       Redistributions of source code must retain the above copyright
// // notice, this list of conditions and the following disclaimer.
// // *       Redistributions in binary form must reproduce the above
// // copyright notice, this list of conditions and the following disclaimer
// // in the documentation and/or other materials provided with the
// // distribution.
// // *       Neither the name of Industrial Light & Magic nor the names of
// // its contributors may be used to endorse or promote products derived
// // from this software without specific prior written permission.
// //
// // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// ///////////////////////////////////////////////////////////////////////////

// // End of OpenEXR license -------------------------------------------------
R
Richard Monette 已提交
75 76 77

THREE.EXRLoader = function ( manager ) {

M
Mugen87 已提交
78 79
	THREE.DataTextureLoader.call( this, manager );

80
	this.type = THREE.FloatType;
R
Richard Monette 已提交
81 82 83

};

M
Mugen87 已提交
84
THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoader.prototype ), {
85

M
Mugen87 已提交
86
	constructor: THREE.EXRLoader,
87

M
Mugen87 已提交
88
	parse: function ( buffer ) {
W
WestLangley 已提交
89

M
Mugen87 已提交
90 91
		const USHORT_RANGE = ( 1 << 16 );
		const BITMAP_SIZE = ( USHORT_RANGE >> 3 );
R
Richard Monette 已提交
92

M
Mugen87 已提交
93 94
		const HUF_ENCBITS = 16; // literal (value) bit length
		const HUF_DECBITS = 14; // decoding bit size (>= 8)
R
Richard Monette 已提交
95

M
Mugen87 已提交
96 97 98
		const HUF_ENCSIZE = ( 1 << HUF_ENCBITS ) + 1; // encoding table size
		const HUF_DECSIZE = 1 << HUF_DECBITS; // decoding table size
		const HUF_DECMASK = HUF_DECSIZE - 1;
R
Richard Monette 已提交
99

M
Mugen87 已提交
100 101 102
		const SHORT_ZEROCODE_RUN = 59;
		const LONG_ZEROCODE_RUN = 63;
		const SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
R
Richard Monette 已提交
103

M
Mugen87 已提交
104
		const BYTES_PER_HALF = 2;
R
Richard Monette 已提交
105

M
Mugen87 已提交
106 107 108 109 110
		const ULONG_SIZE = 8;
		const FLOAT32_SIZE = 4;
		const INT32_SIZE = 4;
		const INT16_SIZE = 2;
		const INT8_SIZE = 1;
R
Richard Monette 已提交
111

M
Mugen87 已提交
112
		function reverseLutFromBitmap( bitmap, lut ) {
113

M
Mugen87 已提交
114
			var k = 0;
M
Mr.doob 已提交
115

M
Mugen87 已提交
116
			for ( var i = 0; i < USHORT_RANGE; ++ i ) {
R
Richard Monette 已提交
117

M
Mugen87 已提交
118
				if ( ( i == 0 ) || ( bitmap[ i >> 3 ] & ( 1 << ( i & 7 ) ) ) ) {
M
Mr.doob 已提交
119

M
Mugen87 已提交
120
					lut[ k ++ ] = i;
M
Mr.doob 已提交
121

M
Mugen87 已提交
122
				}
M
Mr.doob 已提交
123

R
Richard Monette 已提交
124
			}
M
Mr.doob 已提交
125

M
Mugen87 已提交
126
			var n = k - 1;
R
Richard Monette 已提交
127

M
Mugen87 已提交
128
			while ( k < USHORT_RANGE ) lut[ k ++ ] = 0;
R
Richard Monette 已提交
129

M
Mugen87 已提交
130
			return n;
R
Richard Monette 已提交
131

M
Mugen87 已提交
132
		}
M
Mr.doob 已提交
133

M
Mugen87 已提交
134
		function hufClearDecTable( hdec ) {
R
Richard Monette 已提交
135

M
Mugen87 已提交
136
			for ( var i = 0; i < HUF_DECSIZE; i ++ ) {
M
Mr.doob 已提交
137

M
Mugen87 已提交
138 139 140 141
				hdec[ i ] = {};
				hdec[ i ].len = 0;
				hdec[ i ].lit = 0;
				hdec[ i ].p = null;
M
Mr.doob 已提交
142

M
Mugen87 已提交
143
			}
M
Mr.doob 已提交
144

R
Richard Monette 已提交
145
		}
M
Mr.doob 已提交
146

M
Mugen87 已提交
147
		const getBitsReturn = { l: 0, c: 0, lc: 0 };
R
Richard Monette 已提交
148

M
Mugen87 已提交
149
		function getBits( nBits, c, lc, uInt8Array, inOffset ) {
M
Mr.doob 已提交
150

M
Mugen87 已提交
151
			while ( lc < nBits ) {
M
Mr.doob 已提交
152

M
Mugen87 已提交
153 154
				c = ( c << 8 ) | parseUint8Array( uInt8Array, inOffset );
				lc += 8;
M
Mr.doob 已提交
155

M
Mugen87 已提交
156
			}
M
Mr.doob 已提交
157

M
Mugen87 已提交
158
			lc -= nBits;
R
Richard Monette 已提交
159

M
Mugen87 已提交
160 161 162
			getBitsReturn.l = ( c >> lc ) & ( ( 1 << nBits ) - 1 );
			getBitsReturn.c = c;
			getBitsReturn.lc = lc;
R
Richard Monette 已提交
163

M
Mugen87 已提交
164
		}
165

M
Mugen87 已提交
166
		const hufTableBuffer = new Array( 59 );
R
Richard Monette 已提交
167

M
Mugen87 已提交
168
		function hufCanonicalCodeTable( hcode ) {
R
Richard Monette 已提交
169

M
Mugen87 已提交
170 171
			for ( var i = 0; i <= 58; ++ i ) hufTableBuffer[ i ] = 0;
			for ( var i = 0; i < HUF_ENCSIZE; ++ i ) hufTableBuffer[ hcode[ i ] ] += 1;
M
Mr.doob 已提交
172

M
Mugen87 已提交
173
			var c = 0;
R
Richard Monette 已提交
174

M
Mugen87 已提交
175
			for ( var i = 58; i > 0; -- i ) {
R
Richard Monette 已提交
176

M
Mugen87 已提交
177 178 179
				var nc = ( ( c + hufTableBuffer[ i ] ) >> 1 );
				hufTableBuffer[ i ] = c;
				c = nc;
M
Mr.doob 已提交
180

M
Mugen87 已提交
181
			}
M
Mr.doob 已提交
182

M
Mugen87 已提交
183
			for ( var i = 0; i < HUF_ENCSIZE; ++ i ) {
R
Richard Monette 已提交
184

M
Mugen87 已提交
185 186
				var l = hcode[ i ];
				if ( l > 0 ) hcode[ i ] = l | ( hufTableBuffer[ l ] ++ << 6 );
M
Mr.doob 已提交
187

M
Mugen87 已提交
188
			}
R
Richard Monette 已提交
189 190

		}
M
Mr.doob 已提交
191

M
Mugen87 已提交
192
		function hufUnpackEncTable( uInt8Array, inDataView, inOffset, ni, im, iM, hcode ) {
R
Richard Monette 已提交
193

M
Mugen87 已提交
194 195 196
			var p = inOffset;
			var c = 0;
			var lc = 0;
M
Mr.doob 已提交
197

M
Mugen87 已提交
198
			for ( ; im <= iM; im ++ ) {
R
Richard Monette 已提交
199

M
Mugen87 已提交
200
				if ( p.value - inOffset.value > ni ) return false;
M
Mr.doob 已提交
201

M
Mugen87 已提交
202
				getBits( 6, c, lc, uInt8Array, p );
M
Mr.doob 已提交
203

M
Mugen87 已提交
204 205 206
				var l = getBitsReturn.l;
				c = getBitsReturn.c;
				lc = getBitsReturn.lc;
R
Richard Monette 已提交
207

M
Mugen87 已提交
208
				hcode[ im ] = l;
R
Richard Monette 已提交
209

M
Mugen87 已提交
210
				if ( l == LONG_ZEROCODE_RUN ) {
M
Mr.doob 已提交
211

M
Mugen87 已提交
212
					if ( p.value - inOffset.value > ni ) {
M
Mr.doob 已提交
213

M
Mugen87 已提交
214
						throw 'Something wrong with hufUnpackEncTable';
M
Mr.doob 已提交
215

M
Mugen87 已提交
216
					}
M
Mr.doob 已提交
217

M
Mugen87 已提交
218
					getBits( 8, c, lc, uInt8Array, p );
R
Richard Monette 已提交
219

M
Mugen87 已提交
220 221 222
					var zerun = getBitsReturn.l + SHORTEST_LONG_RUN;
					c = getBitsReturn.c;
					lc = getBitsReturn.lc;
M
Mr.doob 已提交
223

M
Mugen87 已提交
224
					if ( im + zerun > iM + 1 ) {
R
Richard Monette 已提交
225

M
Mugen87 已提交
226
						throw 'Something wrong with hufUnpackEncTable';
M
Mr.doob 已提交
227

M
Mugen87 已提交
228
					}
M
Mr.doob 已提交
229

M
Mugen87 已提交
230
					while ( zerun -- ) hcode[ im ++ ] = 0;
R
Richard Monette 已提交
231

M
Mugen87 已提交
232
					im --;
M
Mr.doob 已提交
233

M
Mugen87 已提交
234
				} else if ( l >= SHORT_ZEROCODE_RUN ) {
M
Mr.doob 已提交
235

M
Mugen87 已提交
236
					var zerun = l - SHORT_ZEROCODE_RUN + 2;
R
Richard Monette 已提交
237

M
Mugen87 已提交
238
					if ( im + zerun > iM + 1 ) {
R
Richard Monette 已提交
239

M
Mugen87 已提交
240
						throw 'Something wrong with hufUnpackEncTable';
M
Mr.doob 已提交
241

M
Mugen87 已提交
242
					}
M
Mr.doob 已提交
243

M
Mugen87 已提交
244
					while ( zerun -- ) hcode[ im ++ ] = 0;
R
Richard Monette 已提交
245

M
Mugen87 已提交
246
					im --;
M
Mr.doob 已提交
247

M
Mugen87 已提交
248
				}
R
Richard Monette 已提交
249 250

			}
M
Mr.doob 已提交
251

M
Mugen87 已提交
252 253
			hufCanonicalCodeTable( hcode );

R
Richard Monette 已提交
254 255
		}

M
Mugen87 已提交
256
		function hufLength( code ) {
M
Mr.doob 已提交
257

M
Mugen87 已提交
258
			return code & 63;
R
Richard Monette 已提交
259

M
Mugen87 已提交
260
		}
261

M
Mugen87 已提交
262
		function hufCode( code ) {
263

M
Mugen87 已提交
264
			return code >> 6;
M
Mr.doob 已提交
265

M
Mugen87 已提交
266
		}
267

M
Mugen87 已提交
268
		function hufBuildDecTable( hcode, im, iM, hdecod ) {
269

M
Mugen87 已提交
270
			for ( ; im <= iM; im ++ ) {
M
Mr.doob 已提交
271

M
Mugen87 已提交
272 273
				var c = hufCode( hcode[ im ] );
				var l = hufLength( hcode[ im ] );
R
Richard Monette 已提交
274

M
Mugen87 已提交
275
				if ( c >> l ) {
R
Richard Monette 已提交
276

M
Mugen87 已提交
277
					throw 'Invalid table entry';
M
Mr.doob 已提交
278

M
Mugen87 已提交
279
				}
R
Richard Monette 已提交
280

M
Mugen87 已提交
281
				if ( l > HUF_DECBITS ) {
M
Mr.doob 已提交
282

M
Mugen87 已提交
283
					var pl = hdecod[ ( c >> ( l - HUF_DECBITS ) ) ];
R
Richard Monette 已提交
284

M
Mugen87 已提交
285
					if ( pl.len ) {
M
Mr.doob 已提交
286

M
Mugen87 已提交
287
						throw 'Invalid table entry';
M
Mr.doob 已提交
288

M
Mugen87 已提交
289
					}
R
Richard Monette 已提交
290

M
Mugen87 已提交
291
					pl.lit ++;
M
Mr.doob 已提交
292

M
Mugen87 已提交
293
					if ( pl.p ) {
R
Richard Monette 已提交
294

M
Mugen87 已提交
295 296
						var p = pl.p;
						pl.p = new Array( pl.lit );
M
Mr.doob 已提交
297

M
Mugen87 已提交
298
						for ( var i = 0; i < pl.lit - 1; ++ i ) {
R
Richard Monette 已提交
299

M
Mugen87 已提交
300
							pl.p[ i ] = p[ i ];
M
Mr.doob 已提交
301

M
Mugen87 已提交
302
						}
M
Mr.doob 已提交
303

M
Mugen87 已提交
304 305 306
					} else {

						pl.p = new Array( 1 );
R
Richard Monette 已提交
307 308

					}
M
Mr.doob 已提交
309

M
Mugen87 已提交
310
					pl.p[ pl.lit - 1 ] = im;
M
Mr.doob 已提交
311

M
Mugen87 已提交
312
				} else if ( l ) {
M
Mr.doob 已提交
313

M
Mugen87 已提交
314
					var plOffset = 0;
R
Richard Monette 已提交
315

M
Mugen87 已提交
316
					for ( var i = 1 << ( HUF_DECBITS - l ); i > 0; i -- ) {
M
Mr.doob 已提交
317

M
Mugen87 已提交
318
						var pl = hdecod[ ( c << ( HUF_DECBITS - l ) ) + plOffset ];
M
Mr.doob 已提交
319

M
Mugen87 已提交
320
						if ( pl.len || pl.p ) {
R
Richard Monette 已提交
321

M
Mugen87 已提交
322
							throw 'Invalid table entry';
M
Mr.doob 已提交
323

M
Mugen87 已提交
324
						}
M
Mr.doob 已提交
325

M
Mugen87 已提交
326 327
						pl.len = l;
						pl.lit = im;
R
Richard Monette 已提交
328

M
Mugen87 已提交
329
						plOffset ++;
M
Mr.doob 已提交
330

R
Richard Monette 已提交
331 332 333
					}

				}
M
Mr.doob 已提交
334

R
Richard Monette 已提交
335
			}
M
Mr.doob 已提交
336

M
Mugen87 已提交
337 338
			return true;

R
Richard Monette 已提交
339 340
		}

M
Mugen87 已提交
341
		const getCharReturn = { c: 0, lc: 0 };
M
Mr.doob 已提交
342

M
Mugen87 已提交
343
		function getChar( c, lc, uInt8Array, inOffset ) {
R
Richard Monette 已提交
344

M
Mugen87 已提交
345 346
			c = ( c << 8 ) | parseUint8Array( uInt8Array, inOffset );
			lc += 8;
M
Mr.doob 已提交
347

M
Mugen87 已提交
348 349
			getCharReturn.c = c;
			getCharReturn.lc = lc;
M
Mr.doob 已提交
350

M
Mugen87 已提交
351
		}
R
Richard Monette 已提交
352

M
Mugen87 已提交
353
		const getCodeReturn = { c: 0, lc: 0 };
M
Mr.doob 已提交
354

M
Mugen87 已提交
355
		function getCode( po, rlc, c, lc, uInt8Array, inDataView, inOffset, outBuffer, outBufferOffset, outBufferEndOffset ) {
R
Richard Monette 已提交
356

M
Mugen87 已提交
357
			if ( po == rlc ) {
M
Mr.doob 已提交
358

M
Mugen87 已提交
359
				if ( lc < 8 ) {
M
Mr.doob 已提交
360

M
Mugen87 已提交
361 362 363
					getChar( c, lc, uInt8Array, inOffset );
					c = getCharReturn.c;
					lc = getCharReturn.lc;
M
Mr.doob 已提交
364

M
Mugen87 已提交
365
				}
M
Mr.doob 已提交
366

M
Mugen87 已提交
367
				lc -= 8;
M
Mr.doob 已提交
368

M
Mugen87 已提交
369 370
				var cs = ( c >> lc );
				var cs = new Uint8Array( [ cs ] )[ 0 ];
R
Richard Monette 已提交
371

M
Mugen87 已提交
372
				if ( outBufferOffset.value + cs > outBufferEndOffset ) {
R
Richard Monette 已提交
373

M
Mugen87 已提交
374
					return false;
M
Mr.doob 已提交
375

M
Mugen87 已提交
376
				}
R
Richard Monette 已提交
377

M
Mugen87 已提交
378
				var s = outBuffer[ outBufferOffset.value - 1 ];
M
Mr.doob 已提交
379

M
Mugen87 已提交
380
				while ( cs -- > 0 ) {
R
Richard Monette 已提交
381

M
Mugen87 已提交
382
					outBuffer[ outBufferOffset.value ++ ] = s;
M
Mr.doob 已提交
383

M
Mugen87 已提交
384
				}
M
Mr.doob 已提交
385

M
Mugen87 已提交
386
			} else if ( outBufferOffset.value < outBufferEndOffset ) {
R
Richard Monette 已提交
387

M
Mugen87 已提交
388
				outBuffer[ outBufferOffset.value ++ ] = po;
M
Mr.doob 已提交
389

M
Mugen87 已提交
390
			} else {
M
Mr.doob 已提交
391

M
Mugen87 已提交
392
				return false;
M
Mr.doob 已提交
393

M
Mugen87 已提交
394
			}
M
Mr.doob 已提交
395

M
Mugen87 已提交
396 397
			getCodeReturn.c = c;
			getCodeReturn.lc = lc;
M
Mr.doob 已提交
398

R
Richard Monette 已提交
399 400
		}

M
Mugen87 已提交
401
		function UInt16( value ) {
R
Richard Monette 已提交
402

M
Mugen87 已提交
403
			return ( value & 0xFFFF );
404

M
Mugen87 已提交
405
		}
M
Mr.doob 已提交
406

M
Mugen87 已提交
407
		function Int16( value ) {
M
Mr.doob 已提交
408

M
Mugen87 已提交
409 410
			var ref = UInt16( value );
			return ( ref > 0x7FFF ) ? ref - 0x10000 : ref;
M
Mr.doob 已提交
411

M
Mugen87 已提交
412
		}
M
Mr.doob 已提交
413

M
Mugen87 已提交
414
		const wdec14Return = { a: 0, b: 0 };
415

M
Mugen87 已提交
416
		function wdec14( l, h ) {
M
Mr.doob 已提交
417

M
Mugen87 已提交
418 419
			var ls = Int16( l );
			var hs = Int16( h );
M
Mr.doob 已提交
420

M
Mugen87 已提交
421 422
			var hi = hs;
			var ai = ls + ( hi & 1 ) + ( hi >> 1 );
R
Richard Monette 已提交
423

M
Mugen87 已提交
424 425
			var as = ai;
			var bs = ai - hi;
R
Richard Monette 已提交
426

M
Mugen87 已提交
427 428
			wdec14Return.a = as;
			wdec14Return.b = bs;
R
Richard Monette 已提交
429

M
Mugen87 已提交
430
		}
M
Mr.doob 已提交
431

M
Mugen87 已提交
432
		function wav2Decode( j, buffer, nx, ox, ny, oy ) {
R
Richard Monette 已提交
433

M
Mugen87 已提交
434 435 436
			var n = ( nx > ny ) ? ny : nx;
			var p = 1;
			var p2;
M
Mr.doob 已提交
437

M
Mugen87 已提交
438
			while ( p <= n ) p <<= 1;
R
Richard Monette 已提交
439

M
Mugen87 已提交
440 441 442
			p >>= 1;
			p2 = p;
			p >>= 1;
R
Richard Monette 已提交
443

M
Mugen87 已提交
444
			while ( p >= 1 ) {
R
Richard Monette 已提交
445

M
Mugen87 已提交
446 447 448 449 450 451 452
				var py = 0;
				var ey = py + oy * ( ny - p2 );
				var oy1 = oy * p;
				var oy2 = oy * p2;
				var ox1 = ox * p;
				var ox2 = ox * p2;
				var i00, i01, i10, i11;
M
Mr.doob 已提交
453

M
Mugen87 已提交
454
				for ( ; py <= ey; py += oy2 ) {
R
Richard Monette 已提交
455

M
Mugen87 已提交
456 457
					var px = py;
					var ex = py + ox * ( nx - p2 );
M
Mr.doob 已提交
458

M
Mugen87 已提交
459
					for ( ; px <= ex; px += ox2 ) {
M
Mr.doob 已提交
460

M
Mugen87 已提交
461 462 463
						var p01 = px + ox1;
						var p10 = px + oy1;
						var p11 = p10 + ox1;
R
Richard Monette 已提交
464

M
Mugen87 已提交
465
						wdec14( buffer[ px + j ], buffer[ p10 + j ] );
R
Richard Monette 已提交
466

M
Mugen87 已提交
467 468
						i00 = wdec14Return.a;
						i10 = wdec14Return.b;
M
Mr.doob 已提交
469

M
Mugen87 已提交
470
						wdec14( buffer[ p01 + j ], buffer[ p11 + j ] );
R
Richard Monette 已提交
471

M
Mugen87 已提交
472 473
						i01 = wdec14Return.a;
						i11 = wdec14Return.b;
M
Mr.doob 已提交
474

M
Mugen87 已提交
475
						wdec14( i00, i01 );
R
Richard Monette 已提交
476

M
Mugen87 已提交
477 478
						buffer[ px + j ] = wdec14Return.a;
						buffer[ p01 + j ] = wdec14Return.b;
M
Mr.doob 已提交
479

M
Mugen87 已提交
480
						wdec14( i10, i11 );
M
Mr.doob 已提交
481

M
Mugen87 已提交
482 483
						buffer[ p10 + j ] = wdec14Return.a;
						buffer[ p11 + j ] = wdec14Return.b;
M
Mr.doob 已提交
484

M
Mugen87 已提交
485
					}
R
Richard Monette 已提交
486

M
Mugen87 已提交
487
					if ( nx & p ) {
R
Richard Monette 已提交
488

M
Mugen87 已提交
489
						var p10 = px + oy1;
M
Mr.doob 已提交
490

M
Mugen87 已提交
491
						wdec14( buffer[ px + j ], buffer[ p10 + j ] );
R
Richard Monette 已提交
492

M
Mugen87 已提交
493 494
						i00 = wdec14Return.a;
						buffer[ p10 + j ] = wdec14Return.b;
M
Mr.doob 已提交
495

M
Mugen87 已提交
496
						buffer[ px + j ] = i00;
M
Mr.doob 已提交
497

M
Mugen87 已提交
498
					}
R
Richard Monette 已提交
499 500

				}
M
Mr.doob 已提交
501

M
Mugen87 已提交
502
				if ( ny & p ) {
R
Richard Monette 已提交
503

M
Mugen87 已提交
504 505
					var px = py;
					var ex = py + ox * ( nx - p2 );
M
Mr.doob 已提交
506

M
Mugen87 已提交
507
					for ( ; px <= ex; px += ox2 ) {
M
Mr.doob 已提交
508

M
Mugen87 已提交
509
						var p01 = px + ox1;
R
Richard Monette 已提交
510

M
Mugen87 已提交
511
						wdec14( buffer[ px + j ], buffer[ p01 + j ] );
R
Richard Monette 已提交
512

M
Mugen87 已提交
513 514
						i00 = wdec14Return.a;
						buffer[ p01 + j ] = wdec14Return.b;
M
Mr.doob 已提交
515

M
Mugen87 已提交
516
						buffer[ px + j ] = i00;
M
Mr.doob 已提交
517

M
Mugen87 已提交
518
					}
R
Richard Monette 已提交
519 520

				}
M
Mr.doob 已提交
521

M
Mugen87 已提交
522 523 524
				p2 = p;
				p >>= 1;

R
Richard Monette 已提交
525 526
			}

M
Mugen87 已提交
527
			return py;
M
Mr.doob 已提交
528

R
Richard Monette 已提交
529 530
		}

M
Mugen87 已提交
531
		function hufDecode( encodingTable, decodingTable, uInt8Array, inDataView, inOffset, ni, rlc, no, outBuffer, outOffset ) {
M
Mr.doob 已提交
532

M
Mugen87 已提交
533 534 535 536
			var c = 0;
			var lc = 0;
			var outBufferEndOffset = no;
			var inOffsetEnd = Math.trunc( inOffset.value + ( ni + 7 ) / 8 );
R
Richard Monette 已提交
537

M
Mugen87 已提交
538
			while ( inOffset.value < inOffsetEnd ) {
M
Mr.doob 已提交
539

M
Mugen87 已提交
540
				getChar( c, lc, uInt8Array, inOffset );
M
Mr.doob 已提交
541

M
Mugen87 已提交
542 543
				c = getCharReturn.c;
				lc = getCharReturn.lc;
M
Mr.doob 已提交
544

M
Mugen87 已提交
545
				while ( lc >= HUF_DECBITS ) {
R
Richard Monette 已提交
546

M
Mugen87 已提交
547 548
					var index = ( c >> ( lc - HUF_DECBITS ) ) & HUF_DECMASK;
					var pl = decodingTable[ index ];
R
Richard Monette 已提交
549

M
Mugen87 已提交
550
					if ( pl.len ) {
M
Mr.doob 已提交
551

M
Mugen87 已提交
552
						lc -= pl.len;
M
Mr.doob 已提交
553

M
Mugen87 已提交
554
						getCode( pl.lit, rlc, c, lc, uInt8Array, inDataView, inOffset, outBuffer, outOffset, outBufferEndOffset );
R
Richard Monette 已提交
555

M
Mugen87 已提交
556 557
						c = getCodeReturn.c;
						lc = getCodeReturn.lc;
M
Mr.doob 已提交
558

M
Mugen87 已提交
559
					} else {
M
Mr.doob 已提交
560

M
Mugen87 已提交
561
						if ( ! pl.p ) {
M
Mr.doob 已提交
562

M
Mugen87 已提交
563
							throw 'hufDecode issues';
M
Mr.doob 已提交
564

M
Mugen87 已提交
565
						}
M
Mr.doob 已提交
566

M
Mugen87 已提交
567
						var j;
R
Richard Monette 已提交
568

M
Mugen87 已提交
569
						for ( j = 0; j < pl.lit; j ++ ) {
R
Richard Monette 已提交
570

M
Mugen87 已提交
571
							var l = hufLength( encodingTable[ pl.p[ j ] ] );
M
Mr.doob 已提交
572

M
Mugen87 已提交
573
							while ( lc < l && inOffset.value < inOffsetEnd ) {
M
Mr.doob 已提交
574

M
Mugen87 已提交
575
								getChar( c, lc, uInt8Array, inOffset );
M
Mr.doob 已提交
576

M
Mugen87 已提交
577 578
								c = getCharReturn.c;
								lc = getCharReturn.lc;
R
Richard Monette 已提交
579

M
Mugen87 已提交
580
							}
M
Mr.doob 已提交
581

M
Mugen87 已提交
582
							if ( lc >= l ) {
R
Richard Monette 已提交
583

M
Mugen87 已提交
584
								if ( hufCode( encodingTable[ pl.p[ j ] ] ) == ( ( c >> ( lc - l ) ) & ( ( 1 << l ) - 1 ) ) ) {
M
Mr.doob 已提交
585

M
Mugen87 已提交
586
									lc -= l;
R
Richard Monette 已提交
587

M
Mugen87 已提交
588
									getCode( pl.p[ j ], rlc, c, lc, uInt8Array, inDataView, inOffset, outBuffer, outOffset, outBufferEndOffset );
M
Mr.doob 已提交
589

M
Mugen87 已提交
590 591
									c = getCodeReturn.c;
									lc = getCodeReturn.lc;
M
Mr.doob 已提交
592

M
Mugen87 已提交
593
									break;
M
Mr.doob 已提交
594

M
Mugen87 已提交
595
								}
M
Mr.doob 已提交
596

R
Richard Monette 已提交
597
							}
M
Mr.doob 已提交
598

R
Richard Monette 已提交
599
						}
M
Mr.doob 已提交
600

M
Mugen87 已提交
601
						if ( j == pl.lit ) {
R
Richard Monette 已提交
602

M
Mugen87 已提交
603
							throw 'hufDecode issues';
M
Mr.doob 已提交
604

M
Mugen87 已提交
605
						}
M
Mr.doob 已提交
606

R
Richard Monette 已提交
607
					}
M
Mr.doob 已提交
608

R
Richard Monette 已提交
609
				}
M
Mr.doob 已提交
610

R
Richard Monette 已提交
611
			}
M
Mr.doob 已提交
612

M
Mugen87 已提交
613
			var i = ( 8 - ni ) & 7;
R
Richard Monette 已提交
614

M
Mugen87 已提交
615 616
			c >>= i;
			lc -= i;
M
Mr.doob 已提交
617

M
Mugen87 已提交
618
			while ( lc > 0 ) {
R
Richard Monette 已提交
619

M
Mugen87 已提交
620
				var pl = decodingTable[ ( c << ( HUF_DECBITS - lc ) ) & HUF_DECMASK ];
M
Mr.doob 已提交
621

M
Mugen87 已提交
622
				if ( pl.len ) {
M
Mr.doob 已提交
623

M
Mugen87 已提交
624
					lc -= pl.len;
R
Richard Monette 已提交
625

M
Mugen87 已提交
626
					getCode( pl.lit, rlc, c, lc, uInt8Array, inDataView, inOffset, outBuffer, outOffset, outBufferEndOffset );
M
Mr.doob 已提交
627

M
Mugen87 已提交
628 629
					c = getCodeReturn.c;
					lc = getCodeReturn.lc;
M
Mr.doob 已提交
630

M
Mugen87 已提交
631
				} else {
M
Mr.doob 已提交
632

M
Mugen87 已提交
633
					throw 'hufDecode issues';
M
Mr.doob 已提交
634

M
Mugen87 已提交
635
				}
M
Mr.doob 已提交
636

R
Richard Monette 已提交
637
			}
M
Mr.doob 已提交
638

M
Mugen87 已提交
639 640
			return true;

R
Richard Monette 已提交
641 642
		}

M
Mugen87 已提交
643
		function hufUncompress( uInt8Array, inDataView, inOffset, nCompressed, outBuffer, outOffset, nRaw ) {
M
Mr.doob 已提交
644

M
Mugen87 已提交
645
			var initialInOffset = inOffset.value;
R
Richard Monette 已提交
646

M
Mugen87 已提交
647 648
			var im = parseUint32( inDataView, inOffset );
			var iM = parseUint32( inDataView, inOffset );
M
Mr.doob 已提交
649

M
Mugen87 已提交
650
			inOffset.value += 4;
R
Richard Monette 已提交
651

M
Mugen87 已提交
652
			var nBits = parseUint32( inDataView, inOffset );
M
Mr.doob 已提交
653

M
Mugen87 已提交
654
			inOffset.value += 4;
M
Mr.doob 已提交
655

M
Mugen87 已提交
656
			if ( im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE ) {
M
Mr.doob 已提交
657

M
Mugen87 已提交
658
				throw 'Something wrong with HUF_ENCSIZE';
R
Richard Monette 已提交
659

M
Mugen87 已提交
660
			}
M
Mr.doob 已提交
661

M
Mugen87 已提交
662 663
			var freq = new Array( HUF_ENCSIZE );
			var hdec = new Array( HUF_DECSIZE );
M
Mr.doob 已提交
664

M
Mugen87 已提交
665
			hufClearDecTable( hdec );
R
Richard Monette 已提交
666

M
Mugen87 已提交
667
			var ni = nCompressed - ( inOffset.value - initialInOffset );
M
Mr.doob 已提交
668

M
Mugen87 已提交
669
			hufUnpackEncTable( uInt8Array, inDataView, inOffset, ni, im, iM, freq );
R
Richard Monette 已提交
670

M
Mugen87 已提交
671
			if ( nBits > 8 * ( nCompressed - ( inOffset.value - initialInOffset ) ) ) {
R
Richard Monette 已提交
672

M
Mugen87 已提交
673
				throw 'Something wrong with hufUncompress';
R
Richard Monette 已提交
674

M
Mugen87 已提交
675
			}
R
Richard Monette 已提交
676

M
Mugen87 已提交
677
			hufBuildDecTable( freq, im, iM, hdec );
M
Mr.doob 已提交
678

M
Mugen87 已提交
679
			hufDecode( freq, hdec, uInt8Array, inDataView, inOffset, nBits, iM, nRaw, outBuffer, outOffset );
R
Richard Monette 已提交
680

M
Mugen87 已提交
681
		}
R
Richard Monette 已提交
682

M
Mugen87 已提交
683
		function applyLut( lut, data, nData ) {
R
Richard Monette 已提交
684

M
Mugen87 已提交
685
			for ( var i = 0; i < nData; ++ i ) {
M
Mr.doob 已提交
686

M
Mugen87 已提交
687
				data[ i ] = lut[ data[ i ] ];
M
Mr.doob 已提交
688

M
Mugen87 已提交
689
			}
M
Mr.doob 已提交
690

R
Richard Monette 已提交
691
		}
M
Mr.doob 已提交
692

M
Mugen87 已提交
693
		function decompressPIZ( outBuffer, outOffset, uInt8Array, inDataView, inOffset, tmpBufSize, num_channels, exrChannelInfos, dataWidth, num_lines ) {
R
Richard Monette 已提交
694

M
Mugen87 已提交
695
			var bitmap = new Uint8Array( BITMAP_SIZE );
M
Mr.doob 已提交
696

M
Mugen87 已提交
697 698
			var minNonZero = parseUint16( inDataView, inOffset );
			var maxNonZero = parseUint16( inDataView, inOffset );
M
Mr.doob 已提交
699

M
Mugen87 已提交
700
			if ( maxNonZero >= BITMAP_SIZE ) {
R
Richard Monette 已提交
701

M
Mugen87 已提交
702
				throw 'Something is wrong with PIZ_COMPRESSION BITMAP_SIZE';
R
Richard Monette 已提交
703

M
Mugen87 已提交
704
			}
M
Mr.doob 已提交
705

M
Mugen87 已提交
706
			if ( minNonZero <= maxNonZero ) {
R
Richard Monette 已提交
707

M
Mugen87 已提交
708
				for ( var i = 0; i < maxNonZero - minNonZero + 1; i ++ ) {
M
Mr.doob 已提交
709

M
Mugen87 已提交
710
					bitmap[ i + minNonZero ] = parseUint8( inDataView, inOffset );
M
Mr.doob 已提交
711

M
Mugen87 已提交
712
				}
M
Mr.doob 已提交
713

R
Richard Monette 已提交
714
			}
M
Mr.doob 已提交
715

M
Mugen87 已提交
716 717
			var lut = new Uint16Array( USHORT_RANGE );
			reverseLutFromBitmap( bitmap, lut );
R
Richard Monette 已提交
718

M
Mugen87 已提交
719
			var length = parseUint32( inDataView, inOffset );
R
Richard Monette 已提交
720

M
Mugen87 已提交
721
			hufUncompress( uInt8Array, inDataView, inOffset, length, outBuffer, outOffset, tmpBufSize );
R
Richard Monette 已提交
722

M
Mugen87 已提交
723
			var pizChannelData = new Array( num_channels );
R
Richard Monette 已提交
724

M
Mugen87 已提交
725
			var outBufferEnd = 0;
R
Richard Monette 已提交
726

M
Mugen87 已提交
727
			for ( var i = 0; i < num_channels; i ++ ) {
R
Richard Monette 已提交
728

M
Mugen87 已提交
729 730 731 732 733 734
				pizChannelData[ i ] = {};
				pizChannelData[ i ][ 'start' ] = outBufferEnd;
				pizChannelData[ i ][ 'end' ] = pizChannelData[ i ][ 'start' ];
				pizChannelData[ i ][ 'nx' ] = dataWidth;
				pizChannelData[ i ][ 'ny' ] = num_lines;
				pizChannelData[ i ][ 'size' ] = 1;
M
Mr.doob 已提交
735

M
Mugen87 已提交
736
				outBufferEnd += pizChannelData[ i ].nx * pizChannelData[ i ].ny * pizChannelData[ i ].size;
M
Mr.doob 已提交
737

M
Mugen87 已提交
738
			}
R
Richard Monette 已提交
739

M
Mugen87 已提交
740
			var fooOffset = 0;
R
Richard Monette 已提交
741

M
Mugen87 已提交
742
			for ( var i = 0; i < num_channels; i ++ ) {
R
Richard Monette 已提交
743

M
Mugen87 已提交
744
				for ( var j = 0; j < pizChannelData[ i ].size; ++ j ) {
M
Mr.doob 已提交
745

M
Mugen87 已提交
746 747 748 749 750 751 752 753
					fooOffset += wav2Decode(
						j + fooOffset,
						outBuffer,
						pizChannelData[ i ].nx,
						pizChannelData[ i ].size,
						pizChannelData[ i ].ny,
						pizChannelData[ i ].nx * pizChannelData[ i ].size
					);
M
Mr.doob 已提交
754

M
Mugen87 已提交
755
				}
M
Mr.doob 已提交
756

R
Richard Monette 已提交
757
			}
M
Mr.doob 已提交
758

M
Mugen87 已提交
759
			applyLut( lut, outBuffer, outBufferEnd );
R
Richard Monette 已提交
760

M
Mugen87 已提交
761
			return true;
R
Richard Monette 已提交
762

M
Mugen87 已提交
763
		}
M
Mr.doob 已提交
764

M
Mugen87 已提交
765
		function parseNullTerminatedString( buffer, offset ) {
R
Richard Monette 已提交
766

M
Mugen87 已提交
767 768
			var uintBuffer = new Uint8Array( buffer );
			var endOffset = 0;
R
Richard Monette 已提交
769

M
Mugen87 已提交
770
			while ( uintBuffer[ offset.value + endOffset ] != 0 ) {
R
Richard Monette 已提交
771

M
Mugen87 已提交
772
				endOffset += 1;
R
Richard Monette 已提交
773

M
Mugen87 已提交
774
			}
R
Richard Monette 已提交
775

M
Mugen87 已提交
776 777 778
			var stringValue = new TextDecoder().decode(
				uintBuffer.slice( offset.value, offset.value + endOffset )
			);
R
Richard Monette 已提交
779

M
Mugen87 已提交
780
			offset.value = offset.value + endOffset + 1;
R
Richard Monette 已提交
781

M
Mugen87 已提交
782
			return stringValue;
R
Richard Monette 已提交
783

M
Mugen87 已提交
784
		}
R
Richard Monette 已提交
785

M
Mugen87 已提交
786
		function parseFixedLengthString( buffer, offset, size ) {
R
Richard Monette 已提交
787

M
Mugen87 已提交
788 789 790
			var stringValue = new TextDecoder().decode(
				new Uint8Array( buffer ).slice( offset.value, offset.value + size )
			);
R
Richard Monette 已提交
791

M
Mugen87 已提交
792
			offset.value = offset.value + size;
R
Richard Monette 已提交
793

M
Mugen87 已提交
794
			return stringValue;
R
Richard Monette 已提交
795

M
Mugen87 已提交
796
		}
R
Richard Monette 已提交
797

M
Mugen87 已提交
798
		function parseUlong( dataView, offset ) {
R
Richard Monette 已提交
799

M
Mugen87 已提交
800
			var uLong = dataView.getUint32( 0, true );
R
Richard Monette 已提交
801

M
Mugen87 已提交
802
			offset.value = offset.value + ULONG_SIZE;
R
Richard Monette 已提交
803

M
Mugen87 已提交
804
			return uLong;
R
Richard Monette 已提交
805

M
Mugen87 已提交
806
		}
R
Richard Monette 已提交
807

M
Mugen87 已提交
808
		function parseUint32( dataView, offset ) {
R
Richard Monette 已提交
809

M
Mugen87 已提交
810
			var Uint32 = dataView.getUint32( offset.value, true );
R
Richard Monette 已提交
811

M
Mugen87 已提交
812
			offset.value = offset.value + INT32_SIZE;
R
Richard Monette 已提交
813

M
Mugen87 已提交
814
			return Uint32;
R
Richard Monette 已提交
815

M
Mugen87 已提交
816
		}
R
Richard Monette 已提交
817

M
Mugen87 已提交
818
		function parseUint8Array( uInt8Array, offset ) {
R
Richard Monette 已提交
819

M
Mugen87 已提交
820
			var Uint8 = uInt8Array[ offset.value ];
821

M
Mugen87 已提交
822
			offset.value = offset.value + INT8_SIZE;
823

M
Mugen87 已提交
824
			return Uint8;
825

M
Mugen87 已提交
826
		}
827

M
Mugen87 已提交
828
		function parseUint8( dataView, offset ) {
829

M
Mugen87 已提交
830
			var Uint8 = dataView.getUint8( offset.value );
R
Richard Monette 已提交
831

M
Mugen87 已提交
832
			offset.value = offset.value + INT8_SIZE;
R
Richard Monette 已提交
833

M
Mugen87 已提交
834
			return Uint8;
R
Richard Monette 已提交
835

M
Mugen87 已提交
836
		}
R
Richard Monette 已提交
837

M
Mugen87 已提交
838
		function parseFloat32( dataView, offset ) {
R
Richard Monette 已提交
839

M
Mugen87 已提交
840
			var float = dataView.getFloat32( offset.value, true );
R
Richard Monette 已提交
841

M
Mugen87 已提交
842
			offset.value += FLOAT32_SIZE;
R
Richard Monette 已提交
843

M
Mugen87 已提交
844
			return float;
R
Richard Monette 已提交
845

M
Mugen87 已提交
846
		}
R
Richard Monette 已提交
847

M
Mugen87 已提交
848 849
		// https://stackoverflow.com/questions/5678432/decompressing-half-precision-floats-in-javascript
		function decodeFloat16( binary ) {
R
Richard Monette 已提交
850

M
Mugen87 已提交
851 852
			var exponent = ( binary & 0x7C00 ) >> 10,
				fraction = binary & 0x03FF;
R
Richard Monette 已提交
853

M
Mugen87 已提交
854 855 856 857 858 859 860 861 862
			return ( binary >> 15 ? - 1 : 1 ) * (
				exponent ?
					(
						exponent === 0x1F ?
							fraction ? NaN : Infinity :
							Math.pow( 2, exponent - 15 ) * ( 1 + fraction / 0x400 )
					) :
					6.103515625e-5 * ( fraction / 0x400 )
			);
R
Richard Monette 已提交
863

M
Mugen87 已提交
864
		}
R
Richard Monette 已提交
865

M
Mugen87 已提交
866
		function parseUint16( dataView, offset ) {
R
Richard Monette 已提交
867

M
Mugen87 已提交
868
			var Uint16 = dataView.getUint16( offset.value, true );
R
Richard Monette 已提交
869

M
Mugen87 已提交
870
			offset.value += INT16_SIZE;
R
Richard Monette 已提交
871

M
Mugen87 已提交
872
			return Uint16;
R
Richard Monette 已提交
873

M
Mugen87 已提交
874
		}
R
Richard Monette 已提交
875

M
Mugen87 已提交
876
		function parseFloat16( buffer, offset ) {
R
Richard Monette 已提交
877

M
Mugen87 已提交
878
			return decodeFloat16( parseUint16( buffer, offset ) );
R
Richard Monette 已提交
879

M
Mugen87 已提交
880
		}
R
Richard Monette 已提交
881

M
Mugen87 已提交
882
		function parseChlist( dataView, buffer, offset, size ) {
R
Richard Monette 已提交
883

M
Mugen87 已提交
884 885
			var startOffset = offset.value;
			var channels = [];
R
Richard Monette 已提交
886

M
Mugen87 已提交
887
			while ( offset.value < ( startOffset + size - 1 ) ) {
R
Richard Monette 已提交
888

M
Mugen87 已提交
889 890 891 892 893 894
				var name = parseNullTerminatedString( buffer, offset );
				var pixelType = parseUint32( dataView, offset ); // TODO: Cast this to UINT, HALF or FLOAT
				var pLinear = parseUint8( dataView, offset );
				offset.value += 3; // reserved, three chars
				var xSampling = parseUint32( dataView, offset );
				var ySampling = parseUint32( dataView, offset );
R
Richard Monette 已提交
895

M
Mugen87 已提交
896 897 898 899 900 901 902
				channels.push( {
					name: name,
					pixelType: pixelType,
					pLinear: pLinear,
					xSampling: xSampling,
					ySampling: ySampling
				} );
R
Richard Monette 已提交
903

M
Mugen87 已提交
904
			}
R
Richard Monette 已提交
905

M
Mugen87 已提交
906
			offset.value += 1;
R
Richard Monette 已提交
907

M
Mugen87 已提交
908
			return channels;
R
Richard Monette 已提交
909

M
Mugen87 已提交
910
		}
R
Richard Monette 已提交
911

M
Mugen87 已提交
912
		function parseChromaticities( dataView, offset ) {
R
Richard Monette 已提交
913

M
Mugen87 已提交
914 915 916 917 918 919 920 921
			var redX = parseFloat32( dataView, offset );
			var redY = parseFloat32( dataView, offset );
			var greenX = parseFloat32( dataView, offset );
			var greenY = parseFloat32( dataView, offset );
			var blueX = parseFloat32( dataView, offset );
			var blueY = parseFloat32( dataView, offset );
			var whiteX = parseFloat32( dataView, offset );
			var whiteY = parseFloat32( dataView, offset );
R
Richard Monette 已提交
922

M
Mugen87 已提交
923
			return { redX: redX, redY: redY, greenX: greenX, greenY: greenY, blueX: blueX, blueY: blueY, whiteX: whiteX, whiteY: whiteY };
R
Richard Monette 已提交
924

M
Mugen87 已提交
925
		}
R
Richard Monette 已提交
926

M
Mugen87 已提交
927
		function parseCompression( dataView, offset ) {
R
Richard Monette 已提交
928

M
Mugen87 已提交
929 930 931 932 933 934 935 936 937 938 939 940
			var compressionCodes = [
				'NO_COMPRESSION',
				'RLE_COMPRESSION',
				'ZIPS_COMPRESSION',
				'ZIP_COMPRESSION',
				'PIZ_COMPRESSION',
				'PXR24_COMPRESSION',
				'B44_COMPRESSION',
				'B44A_COMPRESSION',
				'DWAA_COMPRESSION',
				'DWAB_COMPRESSION'
			];
R
Richard Monette 已提交
941

M
Mugen87 已提交
942
			var compression = parseUint8( dataView, offset );
R
Richard Monette 已提交
943

M
Mugen87 已提交
944
			return compressionCodes[ compression ];
R
Richard Monette 已提交
945

M
Mugen87 已提交
946
		}
R
Richard Monette 已提交
947

M
Mugen87 已提交
948
		function parseBox2i( dataView, offset ) {
R
Richard Monette 已提交
949

M
Mugen87 已提交
950 951 952 953
			var xMin = parseUint32( dataView, offset );
			var yMin = parseUint32( dataView, offset );
			var xMax = parseUint32( dataView, offset );
			var yMax = parseUint32( dataView, offset );
R
Richard Monette 已提交
954

M
Mugen87 已提交
955
			return { xMin: xMin, yMin: yMin, xMax: xMax, yMax: yMax };
R
Richard Monette 已提交
956

M
Mugen87 已提交
957
		}
R
Richard Monette 已提交
958

M
Mugen87 已提交
959
		function parseLineOrder( dataView, offset ) {
R
Richard Monette 已提交
960

M
Mugen87 已提交
961 962 963
			var lineOrders = [
				'INCREASING_Y'
			];
R
Richard Monette 已提交
964

M
Mugen87 已提交
965
			var lineOrder = parseUint8( dataView, offset );
R
Richard Monette 已提交
966

M
Mugen87 已提交
967
			return lineOrders[ lineOrder ];
R
Richard Monette 已提交
968

M
Mugen87 已提交
969
		}
R
Richard Monette 已提交
970

M
Mugen87 已提交
971
		function parseV2f( dataView, offset ) {
R
Richard Monette 已提交
972

M
Mugen87 已提交
973 974
			var x = parseFloat32( dataView, offset );
			var y = parseFloat32( dataView, offset );
R
Richard Monette 已提交
975

M
Mugen87 已提交
976
			return [ x, y ];
R
Richard Monette 已提交
977

M
Mugen87 已提交
978
		}
R
Richard Monette 已提交
979

M
Mugen87 已提交
980
		function parseValue( dataView, buffer, offset, type, size ) {
R
Richard Monette 已提交
981

M
Mugen87 已提交
982
			if ( type === 'string' || type === 'iccProfile' ) {
R
Richard Monette 已提交
983

M
Mugen87 已提交
984
				return parseFixedLengthString( buffer, offset, size );
R
Richard Monette 已提交
985

M
Mugen87 已提交
986
			} else if ( type === 'chlist' ) {
R
Richard Monette 已提交
987

M
Mugen87 已提交
988
				return parseChlist( dataView, buffer, offset, size );
R
Richard Monette 已提交
989

M
Mugen87 已提交
990
			} else if ( type === 'chromaticities' ) {
R
Richard Monette 已提交
991

M
Mugen87 已提交
992
				return parseChromaticities( dataView, offset );
R
Richard Monette 已提交
993

M
Mugen87 已提交
994
			} else if ( type === 'compression' ) {
R
Richard Monette 已提交
995

M
Mugen87 已提交
996
				return parseCompression( dataView, offset );
R
Richard Monette 已提交
997

M
Mugen87 已提交
998
			} else if ( type === 'box2i' ) {
R
Richard Monette 已提交
999

M
Mugen87 已提交
1000
				return parseBox2i( dataView, offset );
R
Richard Monette 已提交
1001

M
Mugen87 已提交
1002
			} else if ( type === 'lineOrder' ) {
R
Richard Monette 已提交
1003

M
Mugen87 已提交
1004
				return parseLineOrder( dataView, offset );
R
Richard Monette 已提交
1005

M
Mugen87 已提交
1006
			} else if ( type === 'float' ) {
R
Richard Monette 已提交
1007

M
Mugen87 已提交
1008
				return parseFloat32( dataView, offset );
R
Richard Monette 已提交
1009

M
Mugen87 已提交
1010
			} else if ( type === 'v2f' ) {
R
Richard Monette 已提交
1011

M
Mugen87 已提交
1012
				return parseV2f( dataView, offset );
R
Richard Monette 已提交
1013

M
Mugen87 已提交
1014
			} else if ( type === 'int' ) {
R
Richard Monette 已提交
1015

M
Mugen87 已提交
1016
				return parseUint32( dataView, offset );
R
Richard Monette 已提交
1017

M
Mugen87 已提交
1018
			} else {
R
Richard Monette 已提交
1019

M
Mugen87 已提交
1020
				throw 'Cannot parse value for unsupported type: ' + type;
R
Richard Monette 已提交
1021

M
Mugen87 已提交
1022
			}
R
Richard Monette 已提交
1023 1024 1025

		}

M
Mugen87 已提交
1026 1027
		var bufferDataView = new DataView( buffer );
		var uInt8Array = new Uint8Array( buffer );
R
Richard Monette 已提交
1028

M
Mugen87 已提交
1029
		var EXRHeader = {};
1030

M
Mugen87 已提交
1031 1032 1033
		bufferDataView.getUint32( 0, true ); // magic
		bufferDataView.getUint8( 4, true ); // versionByteZero
		bufferDataView.getUint8( 5, true ); // fullMask
R
Richard Monette 已提交
1034

M
Mugen87 已提交
1035
		// start of header
R
Richard Monette 已提交
1036

M
Mugen87 已提交
1037
		var offset = { value: 8 }; // start at 8, after magic stuff
R
Richard Monette 已提交
1038

M
Mugen87 已提交
1039
		var keepReading = true;
R
Richard Monette 已提交
1040

M
Mugen87 已提交
1041
		while ( keepReading ) {
R
Richard Monette 已提交
1042

M
Mugen87 已提交
1043
			var attributeName = parseNullTerminatedString( buffer, offset );
R
Richard Monette 已提交
1044

M
Mugen87 已提交
1045
			if ( attributeName == 0 ) {
R
Richard Monette 已提交
1046

M
Mugen87 已提交
1047
				keepReading = false;
R
Richard Monette 已提交
1048

M
Mugen87 已提交
1049
			} else {
R
Richard Monette 已提交
1050

M
Mugen87 已提交
1051 1052 1053
				var attributeType = parseNullTerminatedString( buffer, offset );
				var attributeSize = parseUint32( bufferDataView, offset );
				var attributeValue = parseValue( bufferDataView, buffer, offset, attributeType, attributeSize );
R
Richard Monette 已提交
1054

M
Mugen87 已提交
1055
				EXRHeader[ attributeName ] = attributeValue;
R
Richard Monette 已提交
1056

M
Mugen87 已提交
1057
			}
R
Richard Monette 已提交
1058 1059 1060

		}

M
Mugen87 已提交
1061
		// offsets
R
Richard Monette 已提交
1062

M
Mugen87 已提交
1063 1064
		var dataWindowHeight = EXRHeader.dataWindow.yMax + 1;
		var scanlineBlockSize = 1; // 1 for NO_COMPRESSION
R
Richard Monette 已提交
1065

M
Mugen87 已提交
1066
		if ( EXRHeader.compression === 'PIZ_COMPRESSION' ) {
M
Mr.doob 已提交
1067

M
Mugen87 已提交
1068
			scanlineBlockSize = 32;
M
Mr.doob 已提交
1069

M
Mugen87 已提交
1070
		}
M
Mr.doob 已提交
1071

M
Mugen87 已提交
1072
		var numBlocks = dataWindowHeight / scanlineBlockSize;
M
Mr.doob 已提交
1073

M
Mugen87 已提交
1074
		for ( var i = 0; i < numBlocks; i ++ ) {
R
Richard Monette 已提交
1075

M
Mugen87 已提交
1076
			parseUlong( bufferDataView, offset ); // scanlineOffset
R
Richard Monette 已提交
1077

M
Mugen87 已提交
1078
		}
R
Richard Monette 已提交
1079

M
Mugen87 已提交
1080
		// we should be passed the scanline offset table, start reading pixel data
R
Richard Monette 已提交
1081

M
Mugen87 已提交
1082 1083 1084
		var width = EXRHeader.dataWindow.xMax - EXRHeader.dataWindow.xMin + 1;
		var height = EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1;
		var numChannels = EXRHeader.channels.length;
R
Richard Monette 已提交
1085

M
Mugen87 已提交
1086
		switch ( this.type ) {
R
Richard Monette 已提交
1087

M
Mugen87 已提交
1088
			case THREE.FloatType:
1089

M
Mugen87 已提交
1090 1091
				var byteArray = new Float32Array( width * height * numChannels );
				break;
1092

M
Mugen87 已提交
1093
			case THREE.HalfFloatType:
1094

M
Mugen87 已提交
1095 1096
				var byteArray = new Uint16Array( width * height * numChannels );
				break;
1097

M
Mugen87 已提交
1098
			default:
1099

M
Mugen87 已提交
1100 1101
				console.error( 'THREE.EXRLoader: unsupported type: ', this.type );
				break;
1102

M
Mugen87 已提交
1103
		}
1104

M
Mugen87 已提交
1105 1106 1107 1108 1109 1110
		var channelOffsets = {
			R: 0,
			G: 1,
			B: 2,
			A: 3
		};
R
Richard Monette 已提交
1111

M
Mugen87 已提交
1112
		if ( EXRHeader.compression === 'NO_COMPRESSION' ) {
R
Richard Monette 已提交
1113

M
Mugen87 已提交
1114
			for ( var y = 0; y < height; y ++ ) {
R
Richard Monette 已提交
1115

M
Mugen87 已提交
1116 1117
				var y_scanline = parseUint32( bufferDataView, offset );
				parseUint32( bufferDataView, offset ); // dataSize
R
Richard Monette 已提交
1118

M
Mugen87 已提交
1119 1120 1121
				for ( var channelID = 0; channelID < EXRHeader.channels.length; channelID ++ ) {

					var cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ];
R
Richard Monette 已提交
1122

M
Mugen87 已提交
1123
					if ( EXRHeader.channels[ channelID ].pixelType === 1 ) { // half
R
Richard Monette 已提交
1124

M
Mugen87 已提交
1125
						for ( var x = 0; x < width; x ++ ) {
1126

M
Mugen87 已提交
1127
							switch ( this.type ) {
R
Richard Monette 已提交
1128

M
Mugen87 已提交
1129
								case THREE.FloatType:
M
Mugen87 已提交
1130

M
Mugen87 已提交
1131 1132
									var val = parseFloat16( bufferDataView, offset );
									break;
1133

M
Mugen87 已提交
1134
								case THREE.HalfFloatType:
1135

M
Mugen87 已提交
1136 1137
									var val = parseUint16( bufferDataView, offset );
									break;
1138

M
Mugen87 已提交
1139
							}
1140

M
Mugen87 已提交
1141
							byteArray[ ( ( ( height - y_scanline ) * ( width * numChannels ) ) + ( x * numChannels ) ) + cOff ] = val;
1142 1143

						}
M
Mugen87 已提交
1144

M
Mugen87 已提交
1145
					} else {
R
Richard Monette 已提交
1146

W
WestLangley 已提交
1147
						throw 'EXRLoader.parse: unsupported pixelType ' + EXRHeader.channels[ channelID ].pixelType + '. Only pixelType is 1 (HALF) is supported.';
R
Richard Monette 已提交
1148

M
Mugen87 已提交
1149
					}
R
Richard Monette 已提交
1150 1151 1152

				}

R
Richard Monette 已提交
1153 1154
			}

M
Mugen87 已提交
1155
		} else if ( EXRHeader.compression === 'PIZ_COMPRESSION' ) {
R
Richard Monette 已提交
1156

M
Mugen87 已提交
1157
			for ( var scanlineBlockIdx = 0; scanlineBlockIdx < height / scanlineBlockSize; scanlineBlockIdx ++ ) {
R
Richard Monette 已提交
1158

M
Mugen87 已提交
1159 1160
				parseUint32( bufferDataView, offset ); // line_no
				parseUint32( bufferDataView, offset ); // data_len
R
Richard Monette 已提交
1161

M
Mugen87 已提交
1162 1163 1164
				var tmpBufferSize = width * scanlineBlockSize * ( EXRHeader.channels.length * BYTES_PER_HALF );
				var tmpBuffer = new Uint16Array( tmpBufferSize );
				var tmpOffset = { value: 0 };
R
Richard Monette 已提交
1165

M
Mugen87 已提交
1166
				decompressPIZ( tmpBuffer, tmpOffset, uInt8Array, bufferDataView, offset, tmpBufferSize, numChannels, EXRHeader.channels, width, scanlineBlockSize );
R
Richard Monette 已提交
1167

M
Mugen87 已提交
1168
				for ( var line_y = 0; line_y < scanlineBlockSize; line_y ++ ) {
R
Richard Monette 已提交
1169

M
Mugen87 已提交
1170
					for ( var channelID = 0; channelID < EXRHeader.channels.length; channelID ++ ) {
R
Richard Monette 已提交
1171

M
Mugen87 已提交
1172
						var cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ];
R
Richard Monette 已提交
1173

M
Mugen87 已提交
1174
						if ( EXRHeader.channels[ channelID ].pixelType === 1 ) { // half
1175

M
Mugen87 已提交
1176
							for ( var x = 0; x < width; x ++ ) {
R
Richard Monette 已提交
1177

M
Mugen87 已提交
1178
								var idx = ( channelID * ( scanlineBlockSize * width ) ) + ( line_y * width ) + x;
R
Richard Monette 已提交
1179

M
Mugen87 已提交
1180
								switch ( this.type ) {
1181

M
Mugen87 已提交
1182
									case THREE.FloatType:
1183

M
Mugen87 已提交
1184 1185
										var val = decodeFloat16( tmpBuffer[ idx ] );
										break;
1186

M
Mugen87 已提交
1187
									case THREE.HalfFloatType:
1188

M
Mugen87 已提交
1189 1190
										var val = tmpBuffer[ idx ];
										break;
1191

M
Mugen87 已提交
1192
								}
1193

M
Mugen87 已提交
1194
								var true_y = line_y + ( scanlineBlockIdx * scanlineBlockSize );
R
Richard Monette 已提交
1195

M
Mugen87 已提交
1196
								byteArray[ ( ( ( height - true_y ) * ( width * numChannels ) ) + ( x * numChannels ) ) + cOff ] = val;
R
Richard Monette 已提交
1197

M
Mugen87 已提交
1198
							}
R
Richard Monette 已提交
1199

M
Mugen87 已提交
1200
						} else {
R
Richard Monette 已提交
1201

W
WestLangley 已提交
1202
							throw 'EXRLoader.parse: unsupported pixelType ' + EXRHeader.channels[ channelID ].pixelType + '. Only pixelType is 1 (HALF) is supported.';
R
Richard Monette 已提交
1203

M
Mugen87 已提交
1204
						}
R
Richard Monette 已提交
1205 1206 1207 1208

					}

				}
R
Richard Monette 已提交
1209 1210 1211

			}

M
Mugen87 已提交
1212
		} else {
R
Richard Monette 已提交
1213

W
WestLangley 已提交
1214
			throw 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported';
R
Richard Monette 已提交
1215

M
Mugen87 已提交
1216
		}
R
Richard Monette 已提交
1217

M
Mugen87 已提交
1218 1219 1220 1221 1222 1223 1224 1225
		return {
			header: EXRHeader,
			width: width,
			height: height,
			data: byteArray,
			format: EXRHeader.channels.length == 4 ? THREE.RGBAFormat : THREE.RGBFormat,
			type: this.type
		};
R
Richard Monette 已提交
1226

W
WestLangley 已提交
1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
	},

	setDataType: function ( value ) {

		this.type = value;
		return this;

	},

	load: function ( url, onLoad, onProgress, onError ) {

		function onLoadCallback( texture, texData ) {

			switch ( texture.type ) {

				case THREE.FloatType:

					texture.encoding = THREE.LinearEncoding;
					texture.minFilter = THREE.LinearFilter;
					texture.magFilter = THREE.LinearFilter;
					texture.generateMipmaps = false;
					texture.flipY = false;
					break;

				case THREE.HalfFloatType:

					texture.encoding = THREE.LinearEncoding;
					texture.minFilter = THREE.LinearFilter;
					texture.magFilter = THREE.LinearFilter;
					texture.generateMipmaps = false;
					texture.flipY = false;
					break;

			}

			if ( onLoad ) onLoad( texture, texData );

		}

		return THREE.DataTextureLoader.prototype.load.call( this, url, onLoadCallback, onProgress, onError );

M
Mugen87 已提交
1268
	}
R
Richard Monette 已提交
1269

M
Mugen87 已提交
1270
} );