73 lines
2.8 KiB
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"
|
|
|