66 lines
2.2 KiB
Nim
66 lines
2.2 KiB
Nim
|
|
||
|
# License of this file:
|
||
|
# Consider this file an extension of tinyexr.h (3-clause BSD)
|
||
|
|
||
|
# import memfiles
|
||
|
import tinyexr_c
|
||
|
import arr_ref
|
||
|
import ../float16/float16
|
||
|
|
||
|
# import std/strutils
|
||
|
|
||
|
{.compile: "miniz.c".}
|
||
|
# Can't include implementation because it's cpp, we'll compile it separately
|
||
|
{.compile("impl.cpp", "-std=c++11 -I.").}
|
||
|
{.passL:"-lstdc++".}
|
||
|
|
||
|
proc free(p: pointer) {.header: "stdlib.h", importc, nodecl, raises: [], gcsafe.}
|
||
|
|
||
|
proc isEXR*(p: pointer, len: int): bool =
|
||
|
IsEXRFromMemory(p, len.csize_t) == TINYEXR_SUCCESS
|
||
|
|
||
|
proc getEXRDimensions*(p: pointer, len: int): (int, int) =
|
||
|
var version: EXRVersion
|
||
|
var ret = ParseEXRVersionFromMemory(version, p, len.csize_t)
|
||
|
assert ret == TINYEXR_SUCCESS, "Can't read EXR version"
|
||
|
var header: EXRHeader
|
||
|
header.InitEXRHeader
|
||
|
var err: const_cstring
|
||
|
ret = ParseEXRHeaderFromMemory(header, version, p, len.csize_t, err)
|
||
|
if ret != TINYEXR_SUCCESS:
|
||
|
if err != nil:
|
||
|
echo "error: " & $err
|
||
|
FreeEXRErrorMessage(err)
|
||
|
else:
|
||
|
echo "undefined exr error"
|
||
|
else:
|
||
|
let width = 1 + header.data_window.max_x - header.data_window.min_x
|
||
|
let height = 1 + header.data_window.max_y - header.data_window.min_y
|
||
|
discard header.FreeEXRHeader
|
||
|
return (width.int, height.int)
|
||
|
|
||
|
proc decodeEXR*(p: pointer, len: int): (int, int, ArrRef[uint16]) =
|
||
|
# TODO: avoid copying by using the internal API directly
|
||
|
# TODO: decode float16 directly
|
||
|
# TODO: why can't I use "float16" on the type?
|
||
|
var img: ptr UncheckedArray[float32]
|
||
|
var width: int32
|
||
|
var height: int32
|
||
|
var err: const_cstring
|
||
|
let ret = LoadEXRFromMemory(img, width, height, p, len.csize_t, err)
|
||
|
if ret != TINYEXR_SUCCESS:
|
||
|
if err != nil:
|
||
|
let errs = $err
|
||
|
FreeEXRErrorMessage(err)
|
||
|
raise newException(ValueError, errs)
|
||
|
else:
|
||
|
raise newException(ValueError, "Undefined tinyEXR error")
|
||
|
|
||
|
var imglen = width*height*4
|
||
|
var pixels = newArrRef[uint16](imglen)
|
||
|
# pixels[0].addr.copyMem(img, imglen*sizeof(Float16))
|
||
|
for i in 0 ..< imglen:
|
||
|
pixels[i] = img[i].tofloat16(clamp=true).uint16
|
||
|
free(img)
|
||
|
return (width.int, height.int, pixels)
|