# 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)