myou-engine/libs/oiio/oiio.nim

73 lines
2.8 KiB
Nim

{.compile("oiio.cpp","-std=c++14").}
{.passL: "-lOpenImageIO -lOpenImageIO_Util".}
type OiioImageFormat* {.size: 4.} = enum
FORMAT_UNKNOWN = 0
FORMAT_BYTE # 8-bit unsigned
FORMAT_SHORT # 16-bit unsigned
FORMAT_HALF # 16-bit float
FORMAT_FLOAT # 32-bit float
template size*(format: OiioImageFormat): int =
case format:
of FORMAT_BYTE: 1
of FORMAT_SHORT: 2
of FORMAT_HALF: 2
of FORMAT_FLOAT: 4
else: 0
proc decode(input: pointer, input_len: int,
output: pointer, output_len: int,
desired_channels: int32, format: OiioImageFormat, is_BGR: var byte,
file_name: cstring): int32 {.importc:"oiio_image_decode", cdecl.}
proc get_attributes(input: pointer, input_len: int,
width: var int32, height: var int32,
channels: var int32, format: var OiioImageFormat,
file_name: cstring): int32 {.importc:"oiio_image_get_attributes", cdecl.}
template has_bytes(p: pointer, bytes: string): bool =
cmpMem(p, bytes.cstring, bytes.len) == 0
proc file_name_from_magic(input: openArray[byte]): string =
if input.len < 10:
return "image"
var p = input[0].addr
# OpenImageIO usually has no trouble detecting the most common formats,
# however it seems we need to give it a file name for some, like EXR.
if p.has_bytes "\x89PNG": return "image.png"
if p.has_bytes "\xFF\xD8\xFF": return "image.jpg"
if p.has_bytes "v/1\x01": return "image.exr"
if p.has_bytes "#?RADIANCE": return "image.hdr"
return "image"
proc oiioImageGetAttributes*(input: openArray[byte]): (int, int, int, OiioImageFormat) =
# returns: width, height, channels, format
doAssert input.len != 0, "input is empty"
let file_name = file_name_from_magic(input)
var w,h,c: int32
var f: OiioImageFormat
var res = get_attributes(input[0].addr, input.len, w,h,c,f, file_name.cstring)
doAssert res != 0, "error getting image attibutes"
doAssert f != FORMAT_UNKNOWN, "unknown image format"
return (w.int, h.int, c.int, f)
proc oiioImageDecode*[T](input: openArray[byte], min_channels = 0): seq[T] =
doAssert input.len != 0, "input is empty"
let file_name = file_name_from_magic(input)
var w,h,c: int32
var f: OiioImageFormat
var res = get_attributes(input[0].addr, input.len, w,h,c,f, file_name.cstring)
doAssert res != 0, "error getting image attibutes"
doAssert w != 0 and h != 0 and c != 0, "invalid image"
let channels = max(min_channels.int32, c)
# let size_in = w * h * c
let size_out = w * h * channels
result.setLen size_out * f.size
var is_BGR: byte
res = decode(input[0].addr, input.len,
result[0].addr, size_out * f.size,
channels, f, is_BGR, file_name.cstring)
doAssert res != 0, "error decoding image"