Quellcode durchsuchen

EXRLoader: fix incorrect 16-bit wavelet decoding

Guilherme Avila vor 5 Jahren
Ursprung
Commit
9531c5a47a
2 geänderte Dateien mit 138 neuen und 34 gelöschten Zeilen
  1. 69 17
      examples/js/loaders/EXRLoader.js
  2. 69 17
      examples/jsm/loaders/EXRLoader.js

+ 69 - 17
examples/js/loaders/EXRLoader.js

@@ -98,6 +98,10 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 		const HUF_DECSIZE = 1 << HUF_DECBITS; // decoding table size
 		const HUF_DECMASK = HUF_DECSIZE - 1;
 
+		const NBITS = 16;
+		const A_OFFSET = 1 << ( NBITS - 1 );
+		const MOD_MASK = ( 1 << NBITS ) - 1;
+
 		const SHORT_ZEROCODE_RUN = 59;
 		const LONG_ZEROCODE_RUN = 63;
 		const SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
@@ -472,8 +476,22 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 		}
 
-		function wav2Decode( buffer, j, nx, ox, ny, oy ) {
+		function wdec16( l, h ) {
+
+			var m = UInt16( l );
+			var d = UInt16( h );
+
+			var bb = ( m - ( d >> 1 ) ) & MOD_MASK;
+			var aa = ( d + bb - A_OFFSET ) & MOD_MASK;
+
+			wdec14Return.a = aa;
+			wdec14Return.b = bb;
+
+		}
 
+		function wav2Decode( buffer, j, nx, ox, ny, oy, mx ) {
+
+			var w14 = mx < ( 1 << 14 );
 			var n = ( nx > ny ) ? ny : nx;
 			var p = 1;
 			var p2;
@@ -505,25 +523,52 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 						var p10 = px + oy1;
 						var p11 = p10 + ox1;
 
-						wdec14( buffer[ px + j ], buffer[ p10 + j ] );
+						if ( w14 ) {
 
-						i00 = wdec14Return.a;
-						i10 = wdec14Return.b;
+							wdec14( buffer[ px + j ], buffer[ p10 + j ] );
 
-						wdec14( buffer[ p01 + j ], buffer[ p11 + j ] );
+							i00 = wdec14Return.a;
+							i10 = wdec14Return.b;
 
-						i01 = wdec14Return.a;
-						i11 = wdec14Return.b;
+							wdec14( buffer[ p01 + j ], buffer[ p11 + j ] );
 
-						wdec14( i00, i01 );
+							i01 = wdec14Return.a;
+							i11 = wdec14Return.b;
 
-						buffer[ px + j ] = wdec14Return.a;
-						buffer[ p01 + j ] = wdec14Return.b;
+							wdec14( i00, i01 );
+
+							buffer[ px + j ] = wdec14Return.a;
+							buffer[ p01 + j ] = wdec14Return.b;
+
+							wdec14( i10, i11 );
 
-						wdec14( i10, i11 );
+							buffer[ p10 + j ] = wdec14Return.a;
+							buffer[ p11 + j ] = wdec14Return.b;
 
-						buffer[ p10 + j ] = wdec14Return.a;
-						buffer[ p11 + j ] = wdec14Return.b;
+						} else {
+
+							wdec16( buffer[ px + j ], buffer[ p10 + j ] );
+
+							i00 = wdec14Return.a;
+							i10 = wdec14Return.b;
+
+							wdec16( buffer[ p01 + j ], buffer[ p11 + j ] );
+
+							i01 = wdec14Return.a;
+							i11 = wdec14Return.b;
+
+							wdec16( i00, i01 );
+
+							buffer[ px + j ] = wdec14Return.a;
+							buffer[ p01 + j ] = wdec14Return.b;
+
+							wdec16( i10, i11 );
+
+							buffer[ p10 + j ] = wdec14Return.a;
+							buffer[ p11 + j ] = wdec14Return.b;
+
+
+						}
 
 					}
 
@@ -531,7 +576,10 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 						var p10 = px + oy1;
 
-						wdec14( buffer[ px + j ], buffer[ p10 + j ] );
+						if ( w14 )
+							wdec14( buffer[ px + j ], buffer[ p10 + j ] );
+						else
+							wdec16( buffer[ px + j ], buffer[ p10 + j ] );
 
 						i00 = wdec14Return.a;
 						buffer[ p10 + j ] = wdec14Return.b;
@@ -551,7 +599,10 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 						var p01 = px + ox1;
 
-						wdec14( buffer[ px + j ], buffer[ p01 + j ] );
+						if ( w14 )
+							wdec14( buffer[ px + j ], buffer[ p01 + j ] );
+						else
+							wdec16( buffer[ px + j ], buffer[ p01 + j ] );
 
 						i00 = wdec14Return.a;
 						buffer[ p01 + j ] = wdec14Return.b;
@@ -1294,7 +1345,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 			// Reverse LUT
 			var lut = new Uint16Array( USHORT_RANGE );
-			reverseLutFromBitmap( bitmap, lut );
+			var maxValue = reverseLutFromBitmap( bitmap, lut );
 
 			var length = parseUint32( inDataView, inOffset );
 
@@ -1314,7 +1365,8 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 						cd.nx,
 						cd.size,
 						cd.ny,
-						cd.nx * cd.size
+						cd.nx * cd.size,
+						maxValue
 					);
 
 				}

+ 69 - 17
examples/jsm/loaders/EXRLoader.js

@@ -113,6 +113,10 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 		const HUF_DECSIZE = 1 << HUF_DECBITS; // decoding table size
 		const HUF_DECMASK = HUF_DECSIZE - 1;
 
+		const NBITS = 16;
+		const A_OFFSET = 1 << ( NBITS - 1 );
+		const MOD_MASK = ( 1 << NBITS ) - 1;
+
 		const SHORT_ZEROCODE_RUN = 59;
 		const LONG_ZEROCODE_RUN = 63;
 		const SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
@@ -487,8 +491,22 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 		}
 
-		function wav2Decode( buffer, j, nx, ox, ny, oy ) {
+		function wdec16( l, h ) {
+
+			var m = UInt16( l );
+			var d = UInt16( h );
+
+			var bb = ( m - ( d >> 1 ) ) & MOD_MASK;
+			var aa = ( d + bb - A_OFFSET ) & MOD_MASK;
+
+			wdec14Return.a = aa;
+			wdec14Return.b = bb;
+
+		}
 
+		function wav2Decode( buffer, j, nx, ox, ny, oy, mx ) {
+
+			var w14 = mx < ( 1 << 14 );
 			var n = ( nx > ny ) ? ny : nx;
 			var p = 1;
 			var p2;
@@ -520,25 +538,52 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 						var p10 = px + oy1;
 						var p11 = p10 + ox1;
 
-						wdec14( buffer[ px + j ], buffer[ p10 + j ] );
+						if ( w14 ) {
 
-						i00 = wdec14Return.a;
-						i10 = wdec14Return.b;
+							wdec14( buffer[ px + j ], buffer[ p10 + j ] );
 
-						wdec14( buffer[ p01 + j ], buffer[ p11 + j ] );
+							i00 = wdec14Return.a;
+							i10 = wdec14Return.b;
 
-						i01 = wdec14Return.a;
-						i11 = wdec14Return.b;
+							wdec14( buffer[ p01 + j ], buffer[ p11 + j ] );
 
-						wdec14( i00, i01 );
+							i01 = wdec14Return.a;
+							i11 = wdec14Return.b;
 
-						buffer[ px + j ] = wdec14Return.a;
-						buffer[ p01 + j ] = wdec14Return.b;
+							wdec14( i00, i01 );
+
+							buffer[ px + j ] = wdec14Return.a;
+							buffer[ p01 + j ] = wdec14Return.b;
+
+							wdec14( i10, i11 );
 
-						wdec14( i10, i11 );
+							buffer[ p10 + j ] = wdec14Return.a;
+							buffer[ p11 + j ] = wdec14Return.b;
 
-						buffer[ p10 + j ] = wdec14Return.a;
-						buffer[ p11 + j ] = wdec14Return.b;
+						} else {
+
+							wdec16( buffer[ px + j ], buffer[ p10 + j ] );
+
+							i00 = wdec14Return.a;
+							i10 = wdec14Return.b;
+
+							wdec16( buffer[ p01 + j ], buffer[ p11 + j ] );
+
+							i01 = wdec14Return.a;
+							i11 = wdec14Return.b;
+
+							wdec16( i00, i01 );
+
+							buffer[ px + j ] = wdec14Return.a;
+							buffer[ p01 + j ] = wdec14Return.b;
+
+							wdec16( i10, i11 );
+
+							buffer[ p10 + j ] = wdec14Return.a;
+							buffer[ p11 + j ] = wdec14Return.b;
+
+
+						}
 
 					}
 
@@ -546,7 +591,10 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 						var p10 = px + oy1;
 
-						wdec14( buffer[ px + j ], buffer[ p10 + j ] );
+						if ( w14 )
+							wdec14( buffer[ px + j ], buffer[ p10 + j ] );
+						else
+							wdec16( buffer[ px + j ], buffer[ p10 + j ] );
 
 						i00 = wdec14Return.a;
 						buffer[ p10 + j ] = wdec14Return.b;
@@ -566,7 +614,10 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 						var p01 = px + ox1;
 
-						wdec14( buffer[ px + j ], buffer[ p01 + j ] );
+						if ( w14 )
+							wdec14( buffer[ px + j ], buffer[ p01 + j ] );
+						else
+							wdec16( buffer[ px + j ], buffer[ p01 + j ] );
 
 						i00 = wdec14Return.a;
 						buffer[ p01 + j ] = wdec14Return.b;
@@ -1309,7 +1360,7 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 			// Reverse LUT
 			var lut = new Uint16Array( USHORT_RANGE );
-			reverseLutFromBitmap( bitmap, lut );
+			var maxValue = reverseLutFromBitmap( bitmap, lut );
 
 			var length = parseUint32( inDataView, inOffset );
 
@@ -1329,7 +1380,8 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 						cd.nx,
 						cd.size,
 						cd.ny,
-						cd.nx * cd.size
+						cd.nx * cd.size,
+						maxValue
 					);
 
 				}