Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Ablesons
three.js
提交
d23e67e7
T
three.js
项目概览
Ablesons
/
three.js
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
three.js
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
d23e67e7
编写于
11月 10, 2019
作者:
W
WestLangley
提交者:
GitHub
11月 10, 2019
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #17904 from sciecode/dev-exrloader
EXRLoader: RLE support and uncompress refactor.
上级
0473c693
0424ecf4
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
519 addition
and
436 deletion
+519
-436
examples/js/loaders/EXRLoader.js
examples/js/loaders/EXRLoader.js
+260
-218
examples/jsm/loaders/EXRLoader.js
examples/jsm/loaders/EXRLoader.js
+259
-218
未找到文件。
examples/js/loaders/EXRLoader.js
浏览文件 @
d23e67e7
/**
* @author Richard M. / https://github.com/richardmonette
* @author ScieCode / http://github.com/sciecode
*
* OpenEXR loader which, currently, supports
reading 16 bit half data, in either
*
uncompressed or PIZ wavelet compressed form
.
* OpenEXR loader which, currently, supports
uncompressed, ZIP(S), RLE and PIZ wavelet compression.
*
Supports reading 16 and 32 bit data format, except for PIZ compression which only reads 16-bit data
.
*
* Referred to the original Industrial Light & Magic OpenEXR implementation and the TinyEXR / Syoyo Fujita
* implementation, so I have preserved their copyright notices.
...
...
@@ -690,83 +691,106 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
}
function
decompressPIZ
(
outBuffer
,
outOffset
,
uInt8Array
,
inDataView
,
inOffset
,
tmpBufSize
,
num_channels
,
exrChannelInfos
,
dataWidth
,
num_lines
)
{
function
predictor
(
source
)
{
var
bitmap
=
new
Uint8Array
(
BITMAP_SIZE
);
for
(
var
t
=
1
;
t
<
source
.
length
;
t
++
)
{
var
minNonZero
=
parseUint16
(
inDataView
,
inOffset
)
;
var
maxNonZero
=
parseUint16
(
inDataView
,
inOffset
)
;
var
d
=
source
[
t
-
1
]
+
source
[
t
]
-
128
;
source
[
t
]
=
d
;
if
(
maxNonZero
>=
BITMAP_SIZE
)
{
}
throw
'
Something is wrong with PIZ_COMPRESSION BITMAP_SIZE
'
;
}
}
function
interleaveScalar
(
source
,
out
)
{
if
(
minNonZero
<=
maxNonZero
)
{
var
t1
=
0
;
var
t2
=
Math
.
floor
(
(
source
.
length
+
1
)
/
2
);
var
s
=
0
;
var
stop
=
source
.
length
-
1
;
for
(
var
i
=
0
;
i
<
maxNonZero
-
minNonZero
+
1
;
i
++
)
{
while
(
true
)
{
bitmap
[
i
+
minNonZero
]
=
parseUint8
(
inDataView
,
inOffset
);
if
(
s
>
stop
)
break
;
out
[
s
++
]
=
source
[
t1
++
];
}
if
(
s
>
stop
)
break
;
out
[
s
++
]
=
source
[
t2
++
];
}
var
lut
=
new
Uint16Array
(
USHORT_RANGE
);
reverseLutFromBitmap
(
bitmap
,
lut
);
}
var
length
=
parseUint32
(
inDataView
,
inOffset
);
function
decodeRunLength
(
source
)
{
hufUncompress
(
uInt8Array
,
inDataView
,
inOffset
,
length
,
outBuffer
,
outOffset
,
tmpBufSize
);
var
size
=
source
.
byteLength
;
var
out
=
new
Array
();
var
p
=
0
;
var
pizChannelData
=
new
Array
(
num_channels
);
var
reader
=
new
DataView
(
source
);
var
outBufferEnd
=
0
;
while
(
size
>
0
)
{
for
(
var
i
=
0
;
i
<
num_channels
;
i
++
)
{
var
l
=
reader
.
getInt8
(
p
++
);
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
;
if
(
l
<
0
)
{
outBufferEnd
+=
pizChannelData
[
i
].
nx
*
pizChannelData
[
i
].
ny
*
pizChannelData
[
i
].
size
;
var
count
=
-
l
;
size
-=
count
+
1
;
}
for
(
var
i
=
0
;
i
<
count
;
i
++
)
{
var
fooOffset
=
0
;
out
.
push
(
reader
.
getUint8
(
p
++
)
)
;
for
(
var
i
=
0
;
i
<
num_channels
;
i
++
)
{
}
for
(
var
j
=
0
;
j
<
pizChannelData
[
i
].
size
;
++
j
)
{
fooOffset
+=
wav2Decode
(
j
+
fooOffset
,
outBuffer
,
pizChannelData
[
i
].
nx
,
pizChannelData
[
i
].
size
,
pizChannelData
[
i
].
ny
,
pizChannelData
[
i
].
nx
*
pizChannelData
[
i
].
size
);
}
else
{
var
count
=
l
;
size
-=
2
;
var
value
=
reader
.
getUint8
(
p
++
);
for
(
var
i
=
0
;
i
<
count
+
1
;
i
++
)
{
out
.
push
(
value
);
}
}
}
applyLut
(
lut
,
outBuffer
,
outBufferEnd
)
;
return
out
;
return
true
;
}
function
uncompressRaw
(
info
)
{
return
new
DataView
(
info
.
array
.
buffer
,
info
.
offset
.
value
,
info
.
size
);
}
function
decompressZIP
(
inDataView
,
offset
,
compressedSize
,
pixelType
)
{
function
uncompressRLE
(
info
)
{
var
compressed
=
info
.
viewer
.
buffer
.
slice
(
info
.
offset
.
value
,
info
.
offset
.
value
+
info
.
size
);
var
raw
;
var
rawBuffer
=
new
Uint8Array
(
decodeRunLength
(
compressed
)
);
var
tmpBuffer
=
new
Uint8Array
(
rawBuffer
.
length
);
predictor
(
rawBuffer
);
// revert predictor
interleaveScalar
(
rawBuffer
,
tmpBuffer
);
// interleave pixels
return
new
DataView
(
tmpBuffer
.
buffer
);
var
compressed
=
new
Uint8Array
(
inDataView
.
buffer
.
slice
(
offset
.
value
,
offset
.
value
+
compressedSize
)
);
}
function
uncompressZIP
(
info
)
{
var
compressed
=
info
.
array
.
slice
(
info
.
offset
.
value
,
info
.
offset
.
value
+
info
.
size
);
if
(
typeof
Zlib
===
'
undefined
'
)
{
...
...
@@ -779,52 +803,109 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
var
rawBuffer
=
new
Uint8Array
(
inflate
.
decompress
().
buffer
);
var
tmpBuffer
=
new
Uint8Array
(
rawBuffer
.
length
);
reconstruct_scalar
(
rawBuffer
);
// reorder pixels
predictor
(
rawBuffer
);
// revert predictor
interleaveScalar
(
rawBuffer
,
tmpBuffer
);
// interleave pixels
interleave_scalar
(
rawBuffer
,
tmpBuffer
);
// interleave pixels
return
new
DataView
(
tmpBuffer
.
buffer
);
if
(
pixelType
==
1
)
{
}
function
uncompressPIZ
(
info
)
{
raw
=
new
Uint16Array
(
tmpBuffer
.
buffer
);
var
inDataView
=
info
.
viewer
;
var
inOffset
=
{
value
:
info
.
offset
.
value
};
}
else
if
(
pixelType
==
2
)
{
var
tmpBufSize
=
info
.
width
*
scanlineBlockSize
*
(
EXRHeader
.
channels
.
length
*
BYTES_PER_HALF
);
var
outBuffer
=
new
Uint16Array
(
tmpBufSize
);
var
outOffset
=
{
value
:
0
};
raw
=
new
Float32Array
(
tmpBuffer
.
buffer
);
var
bitmap
=
new
Uint8Array
(
BITMAP_SIZE
);
var
minNonZero
=
parseUint16
(
inDataView
,
inOffset
);
var
maxNonZero
=
parseUint16
(
inDataView
,
inOffset
);
if
(
maxNonZero
>=
BITMAP_SIZE
)
{
throw
'
Something is wrong with PIZ_COMPRESSION BITMAP_SIZE
'
;
}
return
raw
;
if
(
minNonZero
<=
maxNonZero
)
{
}
for
(
var
i
=
0
;
i
<
maxNonZero
-
minNonZero
+
1
;
i
++
)
{
function
reconstruct_scalar
(
source
)
{
bitmap
[
i
+
minNonZero
]
=
parseUint8
(
inDataView
,
inOffset
);
for
(
let
t
=
1
;
t
<
source
.
length
;
t
++
)
{
}
var
d
=
source
[
t
-
1
]
+
source
[
t
]
-
128
;
source
[
t
]
=
d
;
}
var
lut
=
new
Uint16Array
(
USHORT_RANGE
);
reverseLutFromBitmap
(
bitmap
,
lut
);
var
length
=
parseUint32
(
inDataView
,
inOffset
);
hufUncompress
(
info
.
array
,
inDataView
,
inOffset
,
length
,
outBuffer
,
outOffset
,
tmpBufSize
);
var
pizChannelData
=
new
Array
(
info
.
channels
);
var
outBufferEnd
=
0
;
for
(
var
i
=
0
;
i
<
info
.
channels
;
i
++
)
{
pizChannelData
[
i
]
=
{};
pizChannelData
[
i
][
'
start
'
]
=
outBufferEnd
;
pizChannelData
[
i
][
'
end
'
]
=
pizChannelData
[
i
][
'
start
'
];
pizChannelData
[
i
][
'
nx
'
]
=
info
.
width
;
pizChannelData
[
i
][
'
ny
'
]
=
info
.
lines
;
pizChannelData
[
i
][
'
size
'
]
=
1
;
outBufferEnd
+=
pizChannelData
[
i
].
nx
*
pizChannelData
[
i
].
ny
*
pizChannelData
[
i
].
size
;
}
}
var
fooOffset
=
0
;
function
interleave_scalar
(
source
,
out
)
{
for
(
var
i
=
0
;
i
<
info
.
channels
;
i
++
)
{
var
t1
=
0
;
var
t2
=
Math
.
floor
(
(
source
.
length
+
1
)
/
2
);
var
s
=
0
;
var
stop
=
source
.
length
-
1
;
for
(
var
j
=
0
;
j
<
pizChannelData
[
i
].
size
;
++
j
)
{
while
(
true
)
{
fooOffset
+=
wav2Decode
(
j
+
fooOffset
,
outBuffer
,
pizChannelData
[
i
].
nx
,
pizChannelData
[
i
].
size
,
pizChannelData
[
i
].
ny
,
pizChannelData
[
i
].
nx
*
pizChannelData
[
i
].
size
);
if
(
s
>
stop
)
break
;
out
[
s
++
]
=
source
[
t1
++
];
}
if
(
s
>
stop
)
break
;
out
[
s
++
]
=
source
[
t2
++
];
}
applyLut
(
lut
,
outBuffer
,
outBufferEnd
);
var
tmpBuffer
=
new
Uint8Array
(
outBuffer
.
buffer
.
byteLength
);
var
tmpOffset
=
0
;
var
n
=
info
.
width
*
2
;
for
(
var
y
=
0
;
y
<
info
.
lines
;
y
++
)
{
for
(
var
c
=
0
;
c
<
info
.
channels
;
c
++
)
{
var
cd
=
pizChannelData
[
c
];
var
cp
=
new
Uint8Array
(
outBuffer
.
buffer
,
cd
.
end
*
2
+
y
*
n
,
n
);
tmpBuffer
.
set
(
cp
,
tmpOffset
);
tmpOffset
+=
n
;
}
}
return
new
DataView
(
tmpBuffer
.
buffer
);
}
function
parseNullTerminatedString
(
buffer
,
offset
)
{
...
...
@@ -1124,17 +1205,92 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
}
// offsets
var
dataWindowHeight
=
EXRHeader
.
dataWindow
.
yMax
+
1
;
var
scanlineBlockSize
=
1
;
// 1 for NO_COMPRESSION
var
uncompress
;
var
scanlineBlockSize
;
switch
(
EXRHeader
.
compression
)
{
if
(
EXRHeader
.
compression
===
'
PIZ_COMPRESSION
'
)
{
case
'
NO_COMPRESSION
'
:
scanlineBlockSize
=
32
;
scanlineBlockSize
=
1
;
uncompress
=
uncompressRaw
;
break
;
}
else
if
(
EXRHeader
.
compression
===
'
ZIP_COMPRESSION
'
)
{
case
'
RLE_COMPRESSION
'
:
scanlineBlockSize
=
1
;
uncompress
=
uncompressRLE
;
break
;
scanlineBlockSize
=
16
;
case
'
ZIPS_COMPRESSION
'
:
scanlineBlockSize
=
1
;
uncompress
=
uncompressZIP
;
break
;
case
'
ZIP_COMPRESSION
'
:
scanlineBlockSize
=
16
;
uncompress
=
uncompressZIP
;
break
;
case
'
PIZ_COMPRESSION
'
:
scanlineBlockSize
=
32
;
uncompress
=
uncompressPIZ
;
break
;
default
:
throw
'
EXRLoader.parse:
'
+
EXRHeader
.
compression
+
'
is unsupported
'
;
}
var
size_t
;
var
getValue
;
// mixed pixelType not supported
var
pixelType
=
EXRHeader
.
channels
[
0
].
pixelType
;
if
(
pixelType
===
1
)
{
// half
switch
(
this
.
type
)
{
case
THREE
.
FloatType
:
getValue
=
parseFloat16
;
size_t
=
INT16_SIZE
;
break
;
case
THREE
.
HalfFloatType
:
getValue
=
parseUint16
;
size_t
=
INT16_SIZE
;
break
;
}
}
else
if
(
pixelType
===
2
)
{
// float
switch
(
this
.
type
)
{
case
THREE
.
FloatType
:
getValue
=
parseFloat32
;
size_t
=
FLOAT32_SIZE
;
break
;
case
THREE
.
HalfFloatType
:
throw
'
EXRLoader.parse: unsupported HalfFloatType texture for FloatType image file.
'
;
}
}
else
{
throw
'
EXRLoader.parse: unsupported pixelType
'
+
pixelType
+
'
for
'
+
EXRHeader
.
compression
+
'
.
'
;
}
...
...
@@ -1196,168 +1352,58 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
A
:
3
};
if
(
EXRHeader
.
compression
===
'
NO_COMPRESSION
'
)
{
for
(
var
y
=
0
;
y
<
height
;
y
++
)
{
var
y_scanline
=
parseUint32
(
bufferDataView
,
offset
);
parseUint32
(
bufferDataView
,
offset
);
// dataSize
var
compressionInfo
=
{
for
(
var
channelID
=
0
;
channelID
<
EXRHeader
.
channels
.
length
;
channelID
++
)
{
var
cOff
=
channelOffsets
[
EXRHeader
.
channels
[
channelID
].
name
];
if
(
EXRHeader
.
channels
[
channelID
].
pixelType
===
1
)
{
// half
for
(
var
x
=
0
;
x
<
width
;
x
++
)
{
array
:
uInt8Array
,
viewer
:
bufferDataView
,
offset
:
offset
,
channels
:
EXRHeader
.
channels
.
length
,
width
:
width
,
lines
:
scanlineBlockSize
,
size
:
0
switch
(
this
.
type
)
{
case
THREE
.
FloatType
:
var
val
=
parseFloat16
(
bufferDataView
,
offset
);
break
;
case
THREE
.
HalfFloatType
:
var
val
=
parseUint16
(
bufferDataView
,
offset
);
break
;
}
byteArray
[
(
(
(
height
-
y_scanline
)
*
(
width
*
numChannels
)
)
+
(
x
*
numChannels
)
)
+
cOff
]
=
val
;
}
}
else
{
throw
'
EXRLoader.parse: unsupported pixelType
'
+
EXRHeader
.
channels
[
channelID
].
pixelType
+
'
for
'
+
EXRHeader
.
compression
+
'
.
'
;
}
};
}
if
(
EXRHeader
.
compression
===
'
NO_COMPRESSION
'
||
EXRHeader
.
compression
===
'
ZIP_COMPRESSION
'
||
EXRHeader
.
compression
===
'
ZIPS_COMPRESSION
'
||
EXRHeader
.
compression
===
'
RLE_COMPRESSION
'
||
EXRHeader
.
compression
===
'
PIZ_COMPRESSION
'
)
{
}
}
else
if
(
EXRHeader
.
compression
===
'
PIZ_COMPRESSION
'
)
{
var
size
;
var
viewer
;
var
tmpOffset
=
{
value
:
0
};
for
(
var
scanlineBlockIdx
=
0
;
scanlineBlockIdx
<
height
/
scanlineBlockSize
;
scanlineBlockIdx
++
)
{
parseUint32
(
bufferDataView
,
offset
);
// line_no
parseUint32
(
bufferDataView
,
offset
);
// data_len
var
tmpBufferSize
=
width
*
scanlineBlockSize
*
(
EXRHeader
.
channels
.
length
*
BYTES_PER_HALF
);
var
tmpBuffer
=
new
Uint16Array
(
tmpBufferSize
);
var
tmpOffset
=
{
value
:
0
};
decompressPIZ
(
tmpBuffer
,
tmpOffset
,
uInt8Array
,
bufferDataView
,
offset
,
tmpBufferSize
,
EXRHeader
.
channels
.
length
,
EXRHeader
.
channels
,
width
,
scanlineBlockSize
);
for
(
var
line_y
=
0
;
line_y
<
scanlineBlockSize
;
line_y
++
)
{
for
(
var
channelID
=
0
;
channelID
<
EXRHeader
.
channels
.
length
;
channelID
++
)
{
var
cOff
=
channelOffsets
[
EXRHeader
.
channels
[
channelID
].
name
];
if
(
EXRHeader
.
channels
[
channelID
].
pixelType
===
1
)
{
// half
for
(
var
x
=
0
;
x
<
width
;
x
++
)
{
var
idx
=
(
channelID
*
(
scanlineBlockSize
*
width
)
)
+
(
line_y
*
width
)
+
x
;
switch
(
this
.
type
)
{
case
THREE
.
FloatType
:
var
val
=
decodeFloat16
(
tmpBuffer
[
idx
]
);
break
;
case
THREE
.
HalfFloatType
:
var
val
=
tmpBuffer
[
idx
];
break
;
}
var
true_y
=
line_y
+
(
scanlineBlockIdx
*
scanlineBlockSize
);
byteArray
[
(
(
(
height
-
true_y
)
*
(
width
*
numChannels
)
)
+
(
x
*
numChannels
)
)
+
cOff
]
=
val
;
}
}
else
{
throw
'
EXRLoader.parse: unsupported pixelType
'
+
EXRHeader
.
channels
[
channelID
].
pixelType
+
'
for
'
+
EXRHeader
.
compression
+
'
.
'
;
}
}
}
size
=
parseUint32
(
bufferDataView
,
offset
);
// data_len
}
compressionInfo
.
offset
=
offset
;
compressionInfo
.
size
=
size
;
}
else
if
(
EXRHeader
.
compression
===
'
ZIP_COMPRESSION
'
||
EXRHeader
.
compression
===
'
ZIPS_COMPRESSION
'
)
{
viewer
=
uncompress
(
compressionInfo
);
for
(
var
scanlineBlockIdx
=
0
;
scanlineBlockIdx
<
height
/
scanlineBlockSize
;
scanlineBlockIdx
++
)
{
parseUint32
(
bufferDataView
,
offset
);
// line_no
var
compressedSize
=
parseUint32
(
bufferDataView
,
offset
);
// data_len
offset
.
value
+=
size
;
var
raw
=
decompressZIP
(
bufferDataView
,
offset
,
compressedSize
,
EXRHeader
.
channels
[
0
].
pixelType
);
for
(
var
line_y
=
0
;
line_y
<
scanlineBlockSize
;
line_y
++
)
{
offset
.
value
+=
compressedSize
;
var
true_y
=
line_y
+
(
scanlineBlockIdx
*
scanlineBlockSize
)
;
for
(
var
line_y
=
0
;
line_y
<
scanlineBlockSize
;
line_y
++
)
{
if
(
true_y
>=
height
)
break
;
for
(
var
channelID
=
0
;
channelID
<
EXRHeader
.
channels
.
length
;
channelID
++
)
{
for
(
var
x
=
0
;
x
<
width
;
x
++
)
{
var
cOff
=
channelOffsets
[
EXRHeader
.
channels
[
channelID
].
name
];
var
cOff
=
channelOffsets
[
EXRHeader
.
channels
[
channelID
].
name
];
for
(
var
x
=
0
;
x
<
width
;
x
++
)
{
var
idx
=
(
line_y
*
(
EXRHeader
.
channels
.
length
*
width
)
)
+
(
channelID
*
width
)
+
x
;
tmpOffset
.
value
=
idx
*
size_t
;
if
(
EXRHeader
.
channels
[
channelID
].
pixelType
===
1
)
{
// half
switch
(
this
.
type
)
{
case
THREE
.
FloatType
:
var
val
=
decodeFloat16
(
raw
[
idx
]
);
break
;
case
THREE
.
HalfFloatType
:
var
val
=
raw
[
idx
];
break
;
}
var
val
=
getValue
(
viewer
,
tmpOffset
);
}
else
if
(
EXRHeader
.
channels
[
channelID
].
pixelType
===
2
)
{
// float
switch
(
this
.
type
)
{
case
THREE
.
FloatType
:
var
val
=
raw
[
idx
];
break
;
case
THREE
.
HalfFloatType
:
throw
'
EXRLoader.parse: unsupported HalfFloatType texture for FloatType image file.
'
;
}
}
else
{
throw
'
EXRLoader.parse: unsupported pixelType
'
+
EXRHeader
.
channels
[
channelID
].
pixelType
+
'
for
'
+
EXRHeader
.
compression
+
'
.
'
;
}
var
true_y
=
line_y
+
(
scanlineBlockIdx
*
scanlineBlockSize
);
byteArray
[
(
(
(
height
-
true_y
)
*
(
width
*
numChannels
)
)
+
(
x
*
numChannels
)
)
+
cOff
]
=
val
;
byteArray
[
(
(
(
height
-
1
-
true_y
)
*
(
width
*
numChannels
)
)
+
(
x
*
numChannels
)
)
+
cOff
]
=
val
;
}
...
...
@@ -1367,10 +1413,6 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
}
}
else
{
throw
'
EXRLoader.parse:
'
+
EXRHeader
.
compression
+
'
is unsupported
'
;
}
return
{
...
...
@@ -1425,4 +1467,4 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
}
}
);
}
);
\ No newline at end of file
examples/jsm/loaders/EXRLoader.js
浏览文件 @
d23e67e7
/**
* @author Richard M. / https://github.com/richardmonette
* @author ScieCode / http://github.com/sciecode
*
* OpenEXR loader which, currently, supports
reading 16 bit half data, in either
*
uncompressed or PIZ wavelet compressed form
.
* OpenEXR loader which, currently, supports
uncompressed, ZIP(S), RLE and PIZ wavelet compression.
*
Supports reading 16 and 32 bit data format, except for PIZ compression which only reads 16-bit data
.
*
* Referred to the original Industrial Light & Magic OpenEXR implementation and the TinyEXR / Syoyo Fujita
* implementation, so I have preserved their copyright notices.
...
...
@@ -701,83 +702,106 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
}
function
decompressPIZ
(
outBuffer
,
outOffset
,
uInt8Array
,
inDataView
,
inOffset
,
tmpBufSize
,
num_channels
,
exrChannelInfos
,
dataWidth
,
num_lines
)
{
function
predictor
(
source
)
{
var
bitmap
=
new
Uint8Array
(
BITMAP_SIZE
);
for
(
var
t
=
1
;
t
<
source
.
length
;
t
++
)
{
var
minNonZero
=
parseUint16
(
inDataView
,
inOffset
)
;
var
maxNonZero
=
parseUint16
(
inDataView
,
inOffset
)
;
var
d
=
source
[
t
-
1
]
+
source
[
t
]
-
128
;
source
[
t
]
=
d
;
if
(
maxNonZero
>=
BITMAP_SIZE
)
{
}
throw
'
Something is wrong with PIZ_COMPRESSION BITMAP_SIZE
'
;
}
}
function
interleaveScalar
(
source
,
out
)
{
if
(
minNonZero
<=
maxNonZero
)
{
var
t1
=
0
;
var
t2
=
Math
.
floor
(
(
source
.
length
+
1
)
/
2
);
var
s
=
0
;
var
stop
=
source
.
length
-
1
;
for
(
var
i
=
0
;
i
<
maxNonZero
-
minNonZero
+
1
;
i
++
)
{
while
(
true
)
{
bitmap
[
i
+
minNonZero
]
=
parseUint8
(
inDataView
,
inOffset
);
if
(
s
>
stop
)
break
;
out
[
s
++
]
=
source
[
t1
++
];
}
if
(
s
>
stop
)
break
;
out
[
s
++
]
=
source
[
t2
++
];
}
var
lut
=
new
Uint16Array
(
USHORT_RANGE
);
reverseLutFromBitmap
(
bitmap
,
lut
);
}
var
length
=
parseUint32
(
inDataView
,
inOffset
);
function
decodeRunLength
(
source
)
{
hufUncompress
(
uInt8Array
,
inDataView
,
inOffset
,
length
,
outBuffer
,
outOffset
,
tmpBufSize
);
var
size
=
source
.
byteLength
;
var
out
=
new
Array
();
var
p
=
0
;
var
pizChannelData
=
new
Array
(
num_channels
);
var
reader
=
new
DataView
(
source
);
var
outBufferEnd
=
0
;
while
(
size
>
0
)
{
for
(
var
i
=
0
;
i
<
num_channels
;
i
++
)
{
var
l
=
reader
.
getInt8
(
p
++
);
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
;
if
(
l
<
0
)
{
outBufferEnd
+=
pizChannelData
[
i
].
nx
*
pizChannelData
[
i
].
ny
*
pizChannelData
[
i
].
size
;
var
count
=
-
l
;
size
-=
count
+
1
;
}
for
(
var
i
=
0
;
i
<
count
;
i
++
)
{
var
fooOffset
=
0
;
out
.
push
(
reader
.
getUint8
(
p
++
)
)
;
for
(
var
i
=
0
;
i
<
num_channels
;
i
++
)
{
}
for
(
var
j
=
0
;
j
<
pizChannelData
[
i
].
size
;
++
j
)
{
fooOffset
+=
wav2Decode
(
j
+
fooOffset
,
outBuffer
,
pizChannelData
[
i
].
nx
,
pizChannelData
[
i
].
size
,
pizChannelData
[
i
].
ny
,
pizChannelData
[
i
].
nx
*
pizChannelData
[
i
].
size
);
}
else
{
var
count
=
l
;
size
-=
2
;
var
value
=
reader
.
getUint8
(
p
++
);
for
(
var
i
=
0
;
i
<
count
+
1
;
i
++
)
{
out
.
push
(
value
);
}
}
}
applyLut
(
lut
,
outBuffer
,
outBufferEnd
)
;
return
out
;
return
true
;
}
function
uncompressRaw
(
info
)
{
return
new
DataView
(
info
.
array
.
buffer
,
info
.
offset
.
value
,
info
.
size
);
}
function
decompressZIP
(
inDataView
,
offset
,
compressedSize
,
pixelType
)
{
function
uncompressRLE
(
info
)
{
var
compressed
=
info
.
viewer
.
buffer
.
slice
(
info
.
offset
.
value
,
info
.
offset
.
value
+
info
.
size
);
var
raw
;
var
rawBuffer
=
new
Uint8Array
(
decodeRunLength
(
compressed
)
);
var
tmpBuffer
=
new
Uint8Array
(
rawBuffer
.
length
);
predictor
(
rawBuffer
);
// revert predictor
interleaveScalar
(
rawBuffer
,
tmpBuffer
);
// interleave pixels
return
new
DataView
(
tmpBuffer
.
buffer
);
var
compressed
=
new
Uint8Array
(
inDataView
.
buffer
.
slice
(
offset
.
value
,
offset
.
value
+
compressedSize
)
);
}
function
uncompressZIP
(
info
)
{
var
compressed
=
info
.
array
.
slice
(
info
.
offset
.
value
,
info
.
offset
.
value
+
info
.
size
);
if
(
typeof
Zlib
===
'
undefined
'
)
{
...
...
@@ -790,52 +814,109 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
var
rawBuffer
=
new
Uint8Array
(
inflate
.
decompress
().
buffer
);
var
tmpBuffer
=
new
Uint8Array
(
rawBuffer
.
length
);
reconstruct_scalar
(
rawBuffer
);
// reorder pixels
predictor
(
rawBuffer
);
// revert predictor
interleaveScalar
(
rawBuffer
,
tmpBuffer
);
// interleave pixels
interleave_scalar
(
rawBuffer
,
tmpBuffer
);
// interleave pixels
return
new
DataView
(
tmpBuffer
.
buffer
);
if
(
pixelType
==
1
)
{
}
function
uncompressPIZ
(
info
)
{
raw
=
new
Uint16Array
(
tmpBuffer
.
buffer
);
var
inDataView
=
info
.
viewer
;
var
inOffset
=
{
value
:
info
.
offset
.
value
};
}
else
if
(
pixelType
==
2
)
{
var
tmpBufSize
=
info
.
width
*
scanlineBlockSize
*
(
EXRHeader
.
channels
.
length
*
BYTES_PER_HALF
);
var
outBuffer
=
new
Uint16Array
(
tmpBufSize
);
var
outOffset
=
{
value
:
0
};
raw
=
new
Float32Array
(
tmpBuffer
.
buffer
);
var
bitmap
=
new
Uint8Array
(
BITMAP_SIZE
);
var
minNonZero
=
parseUint16
(
inDataView
,
inOffset
);
var
maxNonZero
=
parseUint16
(
inDataView
,
inOffset
);
if
(
maxNonZero
>=
BITMAP_SIZE
)
{
throw
'
Something is wrong with PIZ_COMPRESSION BITMAP_SIZE
'
;
}
return
raw
;
if
(
minNonZero
<=
maxNonZero
)
{
}
for
(
var
i
=
0
;
i
<
maxNonZero
-
minNonZero
+
1
;
i
++
)
{
function
reconstruct_scalar
(
source
)
{
bitmap
[
i
+
minNonZero
]
=
parseUint8
(
inDataView
,
inOffset
);
for
(
let
t
=
1
;
t
<
source
.
length
;
t
++
)
{
}
var
d
=
source
[
t
-
1
]
+
source
[
t
]
-
128
;
source
[
t
]
=
d
;
}
var
lut
=
new
Uint16Array
(
USHORT_RANGE
);
reverseLutFromBitmap
(
bitmap
,
lut
);
var
length
=
parseUint32
(
inDataView
,
inOffset
);
hufUncompress
(
info
.
array
,
inDataView
,
inOffset
,
length
,
outBuffer
,
outOffset
,
tmpBufSize
);
var
pizChannelData
=
new
Array
(
info
.
channels
);
var
outBufferEnd
=
0
;
for
(
var
i
=
0
;
i
<
info
.
channels
;
i
++
)
{
pizChannelData
[
i
]
=
{};
pizChannelData
[
i
][
'
start
'
]
=
outBufferEnd
;
pizChannelData
[
i
][
'
end
'
]
=
pizChannelData
[
i
][
'
start
'
];
pizChannelData
[
i
][
'
nx
'
]
=
info
.
width
;
pizChannelData
[
i
][
'
ny
'
]
=
info
.
lines
;
pizChannelData
[
i
][
'
size
'
]
=
1
;
outBufferEnd
+=
pizChannelData
[
i
].
nx
*
pizChannelData
[
i
].
ny
*
pizChannelData
[
i
].
size
;
}
}
var
fooOffset
=
0
;
function
interleave_scalar
(
source
,
out
)
{
for
(
var
i
=
0
;
i
<
info
.
channels
;
i
++
)
{
var
t1
=
0
;
var
t2
=
Math
.
floor
(
(
source
.
length
+
1
)
/
2
);
var
s
=
0
;
var
stop
=
source
.
length
-
1
;
for
(
var
j
=
0
;
j
<
pizChannelData
[
i
].
size
;
++
j
)
{
while
(
true
)
{
fooOffset
+=
wav2Decode
(
j
+
fooOffset
,
outBuffer
,
pizChannelData
[
i
].
nx
,
pizChannelData
[
i
].
size
,
pizChannelData
[
i
].
ny
,
pizChannelData
[
i
].
nx
*
pizChannelData
[
i
].
size
);
if
(
s
>
stop
)
break
;
out
[
s
++
]
=
source
[
t1
++
];
}
if
(
s
>
stop
)
break
;
out
[
s
++
]
=
source
[
t2
++
];
}
applyLut
(
lut
,
outBuffer
,
outBufferEnd
);
var
tmpBuffer
=
new
Uint8Array
(
outBuffer
.
buffer
.
byteLength
);
var
tmpOffset
=
0
;
var
n
=
info
.
width
*
2
;
for
(
var
y
=
0
;
y
<
info
.
lines
;
y
++
)
{
for
(
var
c
=
0
;
c
<
info
.
channels
;
c
++
)
{
var
cd
=
pizChannelData
[
c
];
var
cp
=
new
Uint8Array
(
outBuffer
.
buffer
,
cd
.
end
*
2
+
y
*
n
,
n
);
tmpBuffer
.
set
(
cp
,
tmpOffset
);
tmpOffset
+=
n
;
}
}
return
new
DataView
(
tmpBuffer
.
buffer
);
}
function
parseNullTerminatedString
(
buffer
,
offset
)
{
...
...
@@ -1135,17 +1216,92 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
}
// offsets
var
dataWindowHeight
=
EXRHeader
.
dataWindow
.
yMax
+
1
;
var
scanlineBlockSize
=
1
;
// 1 for NO_COMPRESSION
var
uncompress
;
var
scanlineBlockSize
;
switch
(
EXRHeader
.
compression
)
{
if
(
EXRHeader
.
compression
===
'
PIZ_COMPRESSION
'
)
{
case
'
NO_COMPRESSION
'
:
scanlineBlockSize
=
32
;
scanlineBlockSize
=
1
;
uncompress
=
uncompressRaw
;
break
;
}
else
if
(
EXRHeader
.
compression
===
'
ZIP_COMPRESSION
'
)
{
case
'
RLE_COMPRESSION
'
:
scanlineBlockSize
=
1
;
uncompress
=
uncompressRLE
;
break
;
scanlineBlockSize
=
16
;
case
'
ZIPS_COMPRESSION
'
:
scanlineBlockSize
=
1
;
uncompress
=
uncompressZIP
;
break
;
case
'
ZIP_COMPRESSION
'
:
scanlineBlockSize
=
16
;
uncompress
=
uncompressZIP
;
break
;
case
'
PIZ_COMPRESSION
'
:
scanlineBlockSize
=
32
;
uncompress
=
uncompressPIZ
;
break
;
default
:
throw
'
EXRLoader.parse:
'
+
EXRHeader
.
compression
+
'
is unsupported
'
;
}
var
size_t
;
var
getValue
;
// mixed pixelType not supported
var
pixelType
=
EXRHeader
.
channels
[
0
].
pixelType
;
if
(
pixelType
===
1
)
{
// half
switch
(
this
.
type
)
{
case
FloatType
:
getValue
=
parseFloat16
;
size_t
=
INT16_SIZE
;
break
;
case
HalfFloatType
:
getValue
=
parseUint16
;
size_t
=
INT16_SIZE
;
break
;
}
}
else
if
(
pixelType
===
2
)
{
// float
switch
(
this
.
type
)
{
case
FloatType
:
getValue
=
parseFloat32
;
size_t
=
FLOAT32_SIZE
;
break
;
case
HalfFloatType
:
throw
'
EXRLoader.parse: unsupported HalfFloatType texture for FloatType image file.
'
;
}
}
else
{
throw
'
EXRLoader.parse: unsupported pixelType
'
+
pixelType
+
'
for
'
+
EXRHeader
.
compression
+
'
.
'
;
}
...
...
@@ -1207,168 +1363,58 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
A
:
3
};
if
(
EXRHeader
.
compression
===
'
NO_COMPRESSION
'
)
{
for
(
var
y
=
0
;
y
<
height
;
y
++
)
{
var
y_scanline
=
parseUint32
(
bufferDataView
,
offset
);
parseUint32
(
bufferDataView
,
offset
);
// dataSize
for
(
var
channelID
=
0
;
channelID
<
EXRHeader
.
channels
.
length
;
channelID
++
)
{
var
cOff
=
channelOffsets
[
EXRHeader
.
channels
[
channelID
].
name
];
if
(
EXRHeader
.
channels
[
channelID
].
pixelType
===
1
)
{
// half
for
(
var
x
=
0
;
x
<
width
;
x
++
)
{
switch
(
this
.
type
)
{
case
FloatType
:
var
val
=
parseFloat16
(
bufferDataView
,
offset
);
break
;
case
HalfFloatType
:
var
val
=
parseUint16
(
bufferDataView
,
offset
);
break
;
}
byteArray
[
(
(
(
height
-
y_scanline
)
*
(
width
*
numChannels
)
)
+
(
x
*
numChannels
)
)
+
cOff
]
=
val
;
}
}
else
{
throw
'
EXRLoader.parse: unsupported pixelType
'
+
EXRHeader
.
channels
[
channelID
].
pixelType
+
'
for
'
+
EXRHeader
.
compression
+
'
.
'
;
var
compressionInfo
=
{
}
array
:
uInt8Array
,
viewer
:
bufferDataView
,
offset
:
offset
,
channels
:
EXRHeader
.
channels
.
length
,
width
:
width
,
lines
:
scanlineBlockSize
,
size
:
0
}
};
}
if
(
EXRHeader
.
compression
===
'
NO_COMPRESSION
'
||
EXRHeader
.
compression
===
'
ZIP_COMPRESSION
'
||
EXRHeader
.
compression
===
'
ZIPS_COMPRESSION
'
||
EXRHeader
.
compression
===
'
RLE_COMPRESSION
'
||
EXRHeader
.
compression
===
'
PIZ_COMPRESSION
'
)
{
}
else
if
(
EXRHeader
.
compression
===
'
PIZ_COMPRESSION
'
)
{
var
size
;
var
viewer
;
var
tmpOffset
=
{
value
:
0
};
for
(
var
scanlineBlockIdx
=
0
;
scanlineBlockIdx
<
height
/
scanlineBlockSize
;
scanlineBlockIdx
++
)
{
parseUint32
(
bufferDataView
,
offset
);
// line_no
parseUint32
(
bufferDataView
,
offset
);
// data_len
var
tmpBufferSize
=
width
*
scanlineBlockSize
*
(
EXRHeader
.
channels
.
length
*
BYTES_PER_HALF
);
var
tmpBuffer
=
new
Uint16Array
(
tmpBufferSize
);
var
tmpOffset
=
{
value
:
0
};
decompressPIZ
(
tmpBuffer
,
tmpOffset
,
uInt8Array
,
bufferDataView
,
offset
,
tmpBufferSize
,
EXRHeader
.
channels
.
length
,
EXRHeader
.
channels
,
width
,
scanlineBlockSize
);
for
(
var
line_y
=
0
;
line_y
<
scanlineBlockSize
;
line_y
++
)
{
for
(
var
channelID
=
0
;
channelID
<
EXRHeader
.
channels
.
length
;
channelID
++
)
{
var
cOff
=
channelOffsets
[
EXRHeader
.
channels
[
channelID
].
name
];
if
(
EXRHeader
.
channels
[
channelID
].
pixelType
===
1
)
{
// half
for
(
var
x
=
0
;
x
<
width
;
x
++
)
{
var
idx
=
(
channelID
*
(
scanlineBlockSize
*
width
)
)
+
(
line_y
*
width
)
+
x
;
switch
(
this
.
type
)
{
case
FloatType
:
size
=
parseUint32
(
bufferDataView
,
offset
);
// data_len
var
val
=
decodeFloat16
(
tmpBuffer
[
idx
]
)
;
break
;
compressionInfo
.
offset
=
offset
;
compressionInfo
.
size
=
size
;
case
HalfFloatType
:
var
val
=
tmpBuffer
[
idx
];
break
;
}
var
true_y
=
line_y
+
(
scanlineBlockIdx
*
scanlineBlockSize
);
byteArray
[
(
(
(
height
-
true_y
)
*
(
width
*
numChannels
)
)
+
(
x
*
numChannels
)
)
+
cOff
]
=
val
;
}
}
else
{
throw
'
EXRLoader.parse: unsupported pixelType
'
+
EXRHeader
.
channels
[
channelID
].
pixelType
+
'
for
'
+
EXRHeader
.
compression
+
'
.
'
;
}
}
}
}
viewer
=
uncompress
(
compressionInfo
);
}
else
if
(
EXRHeader
.
compression
===
'
ZIP_COMPRESSION
'
||
EXRHeader
.
compression
===
'
ZIPS_COMPRESSION
'
)
{
offset
.
value
+=
size
;
for
(
var
scanlineBlockIdx
=
0
;
scanlineBlockIdx
<
height
/
scanlineBlockSize
;
scanlineBlockIdx
++
)
{
parseUint32
(
bufferDataView
,
offset
);
// line_no
var
compressedSize
=
parseUint32
(
bufferDataView
,
offset
);
// data_len
for
(
var
line_y
=
0
;
line_y
<
scanlineBlockSize
;
line_y
++
)
{
var
raw
=
decompressZIP
(
bufferDataView
,
offset
,
compressedSize
,
EXRHeader
.
channels
[
0
].
pixelTyp
e
);
var
true_y
=
line_y
+
(
scanlineBlockIdx
*
scanlineBlockSiz
e
);
offset
.
value
+=
compressedSize
;
for
(
var
line_y
=
0
;
line_y
<
scanlineBlockSize
;
line_y
++
)
{
if
(
true_y
>=
height
)
break
;
for
(
var
channelID
=
0
;
channelID
<
EXRHeader
.
channels
.
length
;
channelID
++
)
{
for
(
var
x
=
0
;
x
<
width
;
x
++
)
{
var
cOff
=
channelOffsets
[
EXRHeader
.
channels
[
channelID
].
name
];
var
cOff
=
channelOffsets
[
EXRHeader
.
channels
[
channelID
].
name
];
for
(
var
x
=
0
;
x
<
width
;
x
++
)
{
var
idx
=
(
line_y
*
(
EXRHeader
.
channels
.
length
*
width
)
)
+
(
channelID
*
width
)
+
x
;
tmpOffset
.
value
=
idx
*
size_t
;
if
(
EXRHeader
.
channels
[
channelID
].
pixelType
===
1
)
{
// half
switch
(
this
.
type
)
{
case
FloatType
:
var
val
=
decodeFloat16
(
raw
[
idx
]
);
break
;
case
HalfFloatType
:
var
val
=
raw
[
idx
];
break
;
}
}
else
if
(
EXRHeader
.
channels
[
channelID
].
pixelType
===
2
)
{
// float
var
val
=
getValue
(
viewer
,
tmpOffset
);
switch
(
this
.
type
)
{
case
FloatType
:
var
val
=
raw
[
idx
];
break
;
case
HalfFloatType
:
throw
'
EXRLoader.parse: unsupported HalfFloatType texture for FloatType image file.
'
;
}
}
else
{
throw
'
EXRLoader.parse: unsupported pixelType
'
+
EXRHeader
.
channels
[
channelID
].
pixelType
+
'
for
'
+
EXRHeader
.
compression
+
'
.
'
;
}
var
true_y
=
line_y
+
(
scanlineBlockIdx
*
scanlineBlockSize
);
byteArray
[
(
(
(
height
-
true_y
)
*
(
width
*
numChannels
)
)
+
(
x
*
numChannels
)
)
+
cOff
]
=
val
;
byteArray
[
(
(
(
height
-
1
-
true_y
)
*
(
width
*
numChannels
)
)
+
(
x
*
numChannels
)
)
+
cOff
]
=
val
;
}
...
...
@@ -1378,10 +1424,6 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
}
}
else
{
throw
'
EXRLoader.parse:
'
+
EXRHeader
.
compression
+
'
is unsupported
'
;
}
return
{
...
...
@@ -1437,5 +1479,4 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
}
}
);
export
{
EXRLoader
};
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录