Add support for OpenImageIO.
This commit is contained in:
parent
5b2a22b2c0
commit
a38138582e
5 changed files with 450 additions and 36 deletions
308
libs/oiio/oiio.cpp
Normal file
308
libs/oiio/oiio.cpp
Normal file
|
@ -0,0 +1,308 @@
|
||||||
|
|
||||||
|
enum ImageFormat {
|
||||||
|
FORMAT_UNKNOWN = 0,
|
||||||
|
FORMAT_BYTE, // 8-bit unsigned
|
||||||
|
FORMAT_SHORT, // 16-bit unsigned
|
||||||
|
FORMAT_HALF, // 16-bit float
|
||||||
|
FORMAT_FLOAT, // 32-bit float
|
||||||
|
MAX_ENUM = 0x7FFFFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
// image_decoder.cpp
|
||||||
|
#include <OpenImageIO/imageio.h>
|
||||||
|
#include <OpenImageIO/filesystem.h>
|
||||||
|
#include <OpenImageIO/imagebufalgo.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <exception>
|
||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace OIIO;
|
||||||
|
|
||||||
|
static ImageFormat type_to_format(TypeDesc type) {
|
||||||
|
switch (type.basetype) {
|
||||||
|
case TypeDesc::UINT8: return FORMAT_BYTE;
|
||||||
|
case TypeDesc::UINT16: return FORMAT_SHORT;
|
||||||
|
case TypeDesc::HALF: return FORMAT_HALF;
|
||||||
|
case TypeDesc::FLOAT: return FORMAT_FLOAT;
|
||||||
|
default: return FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* type_to_string(TypeDesc type) {
|
||||||
|
switch (type.basetype) {
|
||||||
|
case TypeDesc::UINT8: return "FORMAT_BYTE";
|
||||||
|
case TypeDesc::UINT16: return "FORMAT_SHORT";
|
||||||
|
case TypeDesc::HALF: return "FORMAT_HALF";
|
||||||
|
case TypeDesc::FLOAT: return "FORMAT_FLOAT";
|
||||||
|
default: return "FORMAT_UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static TypeDesc format_to_type(enum ImageFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case FORMAT_BYTE: return TypeDesc::UINT8; // 8-bit unsigned
|
||||||
|
case FORMAT_SHORT: return TypeDesc::UINT16; // 16-bit unsigned
|
||||||
|
case FORMAT_HALF: return TypeDesc::HALF; // 16-bit float
|
||||||
|
case FORMAT_FLOAT: return TypeDesc::FLOAT; // 32-bit float
|
||||||
|
default: return TypeDesc::UNKNOWN; // Unknown format
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
int oiio_image_decode(const uint8_t* input, size_t input_len,
|
||||||
|
uint8_t* output, size_t output_len,
|
||||||
|
int32_t desired_channels, ImageFormat format, char* is_BGR, const char* file_name) {
|
||||||
|
if (!input || !output || desired_channels < 1 || desired_channels > 4) {
|
||||||
|
fprintf(stderr, "Invalid input parameters\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* decoded = output;
|
||||||
|
bool free_decoded = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto mem_reader = Filesystem::IOMemReader(input, input_len);
|
||||||
|
|
||||||
|
auto in = ImageInput::open(file_name, nullptr, &mem_reader);
|
||||||
|
if (!in) {
|
||||||
|
fprintf(stderr, "Open failed: %s\n", geterror().c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImageSpec& spec = in->spec();
|
||||||
|
*is_BGR = spec.channelnames[0] == "B"? 1:0;
|
||||||
|
const size_t required = spec.width * spec.height * desired_channels;
|
||||||
|
const TypeDesc ftype = format_to_type(format);
|
||||||
|
if (output_len != required * ftype.size()) {
|
||||||
|
fprintf(stderr, "Buffer size mismatch: Needed %zu, got %u\n",
|
||||||
|
required * ftype.size(), output_len);
|
||||||
|
in->close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(spec.nchannels != desired_channels){
|
||||||
|
// have a separate buffer for the decoded image, free later
|
||||||
|
decoded = (uint8_t*)malloc(spec.image_bytes());
|
||||||
|
free_decoded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in->read_image(0, 0, 0, spec.nchannels, ftype, decoded)) {
|
||||||
|
fprintf(stderr, "Read error: %s\n", in->geterror().c_str());
|
||||||
|
in->close();
|
||||||
|
if(free_decoded) free(decoded);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(spec.nchannels < desired_channels){
|
||||||
|
// expand channels
|
||||||
|
ImageSpec src_spec(spec.width, spec.height, spec.nchannels, ftype);
|
||||||
|
ImageBuf src_buf(src_spec, decoded);
|
||||||
|
ImageSpec dst_spec(spec.width, spec.height, desired_channels, ftype);
|
||||||
|
ImageBuf dst_buf(dst_spec, output);
|
||||||
|
|
||||||
|
const float channel_values[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
// -1 below fills with the values above
|
||||||
|
std::array<int, 4> channel_order = {-1, -1, -1, -1};
|
||||||
|
for(int i=0; i<spec.nchannels; i++){
|
||||||
|
channel_order[i] = i;
|
||||||
|
}
|
||||||
|
if(spec.nchannels == 1 && desired_channels >= 3){
|
||||||
|
// single channel exception: make it greyscale RGB/RGBA
|
||||||
|
channel_order = {0,0,0,-1};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImageBufAlgo::channels(dst_buf, src_buf,
|
||||||
|
desired_channels,
|
||||||
|
channel_order, channel_values)) {
|
||||||
|
fprintf(stderr, "Channel conversion failed: %s\n", dst_buf.geterror().c_str());
|
||||||
|
in->close();
|
||||||
|
if(free_decoded) free(decoded);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint8_t* pixels = (uint8_t*)dst_buf.localpixels();
|
||||||
|
if(pixels != output){
|
||||||
|
// it turns out channels() always resets the buffer
|
||||||
|
// so it's no longer wrapping output
|
||||||
|
memcpy(output, pixels, dst_spec.image_bytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in->close();
|
||||||
|
if(free_decoded) free(decoded);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
fprintf(stderr, "Exception: %s\n", e.what());
|
||||||
|
if(free_decoded) free(decoded);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
fprintf(stderr, "Unknown exception occurred\n");
|
||||||
|
if(free_decoded) free(decoded);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int oiio_image_get_attributes(const uint8_t* input, size_t input_len,
|
||||||
|
int32_t* width, int32_t* height, int32_t* channels,
|
||||||
|
enum ImageFormat* format, const char* file_name) {
|
||||||
|
if (!input) {
|
||||||
|
fprintf(stderr, "Null input buffer\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto mem_reader = Filesystem::IOMemReader(input, input_len);
|
||||||
|
|
||||||
|
auto in = ImageInput::open(file_name, nullptr, &mem_reader);
|
||||||
|
if (!in) {
|
||||||
|
fprintf(stderr, "Open failed: %s\n", geterror().c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImageSpec& spec = in->spec();
|
||||||
|
if (width) *width = spec.width;
|
||||||
|
if (height) *height = spec.height;
|
||||||
|
if (channels) *channels = spec.nchannels;
|
||||||
|
if (format) *format = type_to_format(spec.format);
|
||||||
|
|
||||||
|
in->close();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
fprintf(stderr, "Exception: %s\n", e.what());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
fprintf(stderr, "Unknown exception occurred\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // image_to_ppm.c
|
||||||
|
// #include <stdio.h>
|
||||||
|
// #include <stdlib.h>
|
||||||
|
|
||||||
|
// int main(int argc, char** argv) {
|
||||||
|
// if (argc != 2) {
|
||||||
|
// fprintf(stderr, "Usage: %s <image-file>\n", argv[0]);
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Read input file
|
||||||
|
// FILE* file = fopen(argv[1], "rb");
|
||||||
|
// if (!file) {
|
||||||
|
// perror("Failed to open file");
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fseek(file, 0, SEEK_END);
|
||||||
|
// long file_size = ftell(file);
|
||||||
|
// fseek(file, 0, SEEK_SET);
|
||||||
|
|
||||||
|
// uint8_t* input = (uint8_t*)malloc(file_size);
|
||||||
|
// if (!input) {
|
||||||
|
// fclose(file);
|
||||||
|
// fprintf(stderr, "Memory allocation failed\n");
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (fread(input, 1, file_size, file) != file_size) {
|
||||||
|
// fclose(file);
|
||||||
|
// free(input);
|
||||||
|
// fprintf(stderr, "File read error\n");
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
// fclose(file);
|
||||||
|
|
||||||
|
// // Get image attributes
|
||||||
|
// int width, height, channels;
|
||||||
|
// enum ImageFormat format;
|
||||||
|
// if (!image_get_attributes(input, file_size, &width, &height, &channels, &format)) {
|
||||||
|
// free(input);
|
||||||
|
// fprintf(stderr, "Unsupported image format\n");
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Allocate output buffer for 3-channel RGB
|
||||||
|
// size_t output_size = width * height * 3;
|
||||||
|
// uint8_t* pixels = (uint8_t*)malloc(output_size);
|
||||||
|
// if (!pixels) {
|
||||||
|
// free(input);
|
||||||
|
// fprintf(stderr, "Output buffer allocation failed\n");
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Decode to 3 channels (RGB)
|
||||||
|
// if (!image_decode(input, file_size, pixels, output_size, 3, format)) {
|
||||||
|
// free(input);
|
||||||
|
// free(pixels);
|
||||||
|
// fprintf(stderr, "Image decoding failed\n");
|
||||||
|
// return 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// free(input);
|
||||||
|
|
||||||
|
// // Output PPM header
|
||||||
|
// printf("P6\n%d %d\n255\n", width, height);
|
||||||
|
|
||||||
|
// // Output raw pixel data
|
||||||
|
// fwrite(pixels, 1, output_size, stdout);
|
||||||
|
|
||||||
|
// free(pixels);
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
bool convertRGBToRGBA(const std::string& filename,
|
||||||
|
void* output_buffer,
|
||||||
|
size_t buffer_length,
|
||||||
|
std::string& error_msg) {
|
||||||
|
// Load source image
|
||||||
|
ImageBuf src_buf(filename);
|
||||||
|
if (!src_buf.read()) {
|
||||||
|
error_msg = "Failed to load image: " + src_buf.geterror();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImageSpec& src_spec = src_buf.spec();
|
||||||
|
|
||||||
|
// Verify source is RGB
|
||||||
|
if (src_spec.nchannels != 3) {
|
||||||
|
error_msg = "Image is not RGB (has " + std::to_string(src_spec.nchannels) + " channels)";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate required buffer size
|
||||||
|
TypeDesc data_type = src_spec.format;
|
||||||
|
const size_t required_size = src_spec.width * src_spec.height * 4 * data_type.size();
|
||||||
|
if (buffer_length < required_size) {
|
||||||
|
error_msg = "Buffer too small. Required: " + std::to_string(required_size) +
|
||||||
|
", provided: " + std::to_string(buffer_length);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare destination buffer wrapped in ImageBuf
|
||||||
|
ImageSpec dst_spec(src_spec.width, src_spec.height, 4, data_type);
|
||||||
|
ImageBuf dst_buf(dst_spec, output_buffer);
|
||||||
|
|
||||||
|
// Set up channel remapping with alpha=1.0
|
||||||
|
const int channel_order[] = {0, 1, 2, -1}; // Source RGB, new alpha
|
||||||
|
const float channel_values[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
|
|
||||||
|
// Perform channel conversion
|
||||||
|
if (!ImageBufAlgo::channels(dst_buf, src_buf,
|
||||||
|
/* channel count */ 4,
|
||||||
|
channel_order, channel_values)) {
|
||||||
|
error_msg = "Channel conversion failed: " + dst_buf.geterror();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
75
libs/oiio/oiio.nim
Normal file
75
libs/oiio/oiio.nim
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
|
||||||
|
import std/strformat
|
||||||
|
|
||||||
|
{.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"
|
||||||
|
|
2
libs/packages/oiio.nim
Normal file
2
libs/packages/oiio.nim
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
import ../oiio/oiio
|
||||||
|
export oiio
|
|
@ -41,11 +41,14 @@ import vmath except Quat, quat
|
||||||
import arr_ref
|
import arr_ref
|
||||||
import float16
|
import float16
|
||||||
|
|
||||||
import stb_image/read as stbi
|
const myouConvertHdrToFloat16 {.booldefine.} = not defined(myouUseOpenImageIO)
|
||||||
const myouConvertHdrToFloat16 {.booldefine.} = true
|
|
||||||
|
|
||||||
when not defined(nimdoc):
|
when defined(myouUseOpenImageIO):
|
||||||
import tinyexr
|
import oiio
|
||||||
|
else:
|
||||||
|
import stb_image/read as stbi
|
||||||
|
when not defined(nimdoc):
|
||||||
|
import tinyexr
|
||||||
|
|
||||||
proc stride*(format: TextureFormat): int =
|
proc stride*(format: TextureFormat): int =
|
||||||
case format:
|
case format:
|
||||||
|
@ -106,7 +109,19 @@ proc f32_to_f16(source: ptr UncheckedArray[float32], dest: ptr UncheckedArray[Fl
|
||||||
dest[i] = source[i].tofloat16(clamp=true)
|
dest[i] = source[i].tofloat16(clamp=true)
|
||||||
|
|
||||||
proc getDimensionsFormat*(p: pointer, len: int, min_channels=0): (int, int, TextureFormat) =
|
proc getDimensionsFormat*(p: pointer, len: int, min_channels=0): (int, int, TextureFormat) =
|
||||||
when not defined(nimdoc):
|
when defined(myouUseOpenImageIO):
|
||||||
|
var (width, height, channels, fmt) = oiioImageGetAttributes(p.toOpenArrayByte(0, len-1))
|
||||||
|
channels = max(min_channels, channels)
|
||||||
|
when myouConvertHdrToFloat16:
|
||||||
|
if fmt == FORMAT_FLOAT: fmt = FORMAT_HALF
|
||||||
|
let format = case fmt:
|
||||||
|
of FORMAT_BYTE: (R_u8.int - 1 + channels).TextureFormat
|
||||||
|
of FORMAT_SHORT: (R_u16.int - 1 + channels).TextureFormat
|
||||||
|
of FORMAT_HALF: (R_f16.int - 1 + channels).TextureFormat
|
||||||
|
of FORMAT_FLOAT: (R_f32.int - 1 + channels).TextureFormat
|
||||||
|
else: R_u8
|
||||||
|
return (width, height, format)
|
||||||
|
elif not defined(nimdoc):
|
||||||
if isEXR(p, len):
|
if isEXR(p, len):
|
||||||
let dims = getEXRDimensions(p, len)
|
let dims = getEXRDimensions(p, len)
|
||||||
return (dims[0], dims[1], RGBA_f16)
|
return (dims[0], dims[1], RGBA_f16)
|
||||||
|
@ -144,42 +159,54 @@ proc loadFileFromSlices*(tex: Texture, slices: seq[SliceMem[byte]],
|
||||||
var out_buffer = newSliceMem[byte](layer_stride * tex.depth)
|
var out_buffer = newSliceMem[byte](layer_stride * tex.depth)
|
||||||
var pos = 0
|
var pos = 0
|
||||||
for slice in slices:
|
for slice in slices:
|
||||||
var image: imagePixelData[byte]
|
|
||||||
var image_16: imagePixelData[uint16]
|
|
||||||
var image_f: imagePixelData[float32]
|
|
||||||
var buffer: ArrRef[byte]
|
|
||||||
# a reference to this pointer is kept with one of the vars above
|
|
||||||
var pixels_ptr: pointer
|
var pixels_ptr: pointer
|
||||||
var pixels_len: int
|
var pixels_len: int
|
||||||
var flip = flip
|
when defined(myouUseOpenImageIO):
|
||||||
if isEXR(slice.data, slice.byte_len):
|
let image = oiioImageDecode[byte](slice.toOpenArrayByte, min_channels)
|
||||||
let (width, height, pixels) = decodeEXR(slice.data, slice.byte_len)
|
pixels_ptr = image[0].addr
|
||||||
assert width == tex.width and height == tex.height, "Image size mismatch"
|
pixels_len = image.len
|
||||||
buffer = pixels.to byte
|
when myouConvertHdrToFloat16:
|
||||||
pixels_ptr = buffer[0].addr
|
if pixels_len == layer_stride * 2:
|
||||||
pixels_len = buffer.len
|
|
||||||
else:
|
|
||||||
setFlipVerticallyOnLoad(flip)
|
|
||||||
flip = false
|
|
||||||
var w,h,c = 0
|
|
||||||
if isHDRFromMemory(slice.toOpenArrayByte):
|
|
||||||
image_f = loadFFromMemory(slice.toOpenArrayByte, w,h,c, min_channels)
|
|
||||||
pixels_ptr = image_f.data
|
|
||||||
pixels_len = image_f.byteLen
|
|
||||||
when myouConvertHdrToFloat16:
|
|
||||||
f32_to_f16(
|
f32_to_f16(
|
||||||
cast[ptr UncheckedArray[float32]](pixels_ptr),
|
cast[ptr UncheckedArray[float32]](pixels_ptr),
|
||||||
cast[ptr UncheckedArray[Float16]](pixels_ptr),
|
cast[ptr UncheckedArray[Float16]](pixels_ptr),
|
||||||
image_f.len)
|
pixels_len div 4)
|
||||||
pixels_len = pixels_len div 2
|
pixels_len = pixels_len div 2
|
||||||
elif is16BitFromMemory(slice.toOpenArrayByte):
|
# var flip = not flip
|
||||||
image_16 = load16FromMemory(slice.toOpenArrayByte, w,h,c, min_channels)
|
else:
|
||||||
pixels_ptr = image_16.data
|
var image: imagePixelData[byte]
|
||||||
pixels_len = image_16.byteLen
|
var image_16: imagePixelData[uint16]
|
||||||
|
var image_f: imagePixelData[float32]
|
||||||
|
var buffer: ArrRef[byte]
|
||||||
|
var flip = flip
|
||||||
|
if isEXR(slice.data, slice.byte_len):
|
||||||
|
let (width, height, pixels) = decodeEXR(slice.data, slice.byte_len)
|
||||||
|
assert width == tex.width and height == tex.height, "Image size mismatch"
|
||||||
|
buffer = pixels.to byte
|
||||||
|
pixels_ptr = buffer[0].addr
|
||||||
|
pixels_len = buffer.len
|
||||||
else:
|
else:
|
||||||
image = loadFromMemory(slice.toOpenArrayByte, w,h,c, min_channels)
|
setFlipVerticallyOnLoad(flip)
|
||||||
pixels_ptr = image.data
|
flip = false
|
||||||
pixels_len = image.len
|
var w,h,c = 0
|
||||||
|
if isHDRFromMemory(slice.toOpenArrayByte):
|
||||||
|
image_f = loadFFromMemory(slice.toOpenArrayByte, w,h,c, min_channels)
|
||||||
|
pixels_ptr = image_f.data
|
||||||
|
pixels_len = image_f.byteLen
|
||||||
|
when myouConvertHdrToFloat16:
|
||||||
|
f32_to_f16(
|
||||||
|
cast[ptr UncheckedArray[float32]](pixels_ptr),
|
||||||
|
cast[ptr UncheckedArray[Float16]](pixels_ptr),
|
||||||
|
image_f.len)
|
||||||
|
pixels_len = pixels_len div 2
|
||||||
|
elif is16BitFromMemory(slice.toOpenArrayByte):
|
||||||
|
image_16 = load16FromMemory(slice.toOpenArrayByte, w,h,c, min_channels)
|
||||||
|
pixels_ptr = image_16.data
|
||||||
|
pixels_len = image_16.byteLen
|
||||||
|
else:
|
||||||
|
image = loadFromMemory(slice.toOpenArrayByte, w,h,c, min_channels)
|
||||||
|
pixels_ptr = image.data
|
||||||
|
pixels_len = image.len
|
||||||
if layer_stride != pixels_len:
|
if layer_stride != pixels_len:
|
||||||
echo "Format: ", format
|
echo "Format: ", format
|
||||||
raise Defect.newException &"Image '{tex.name}' has a length" &
|
raise Defect.newException &"Image '{tex.name}' has a length" &
|
||||||
|
|
|
@ -430,8 +430,10 @@ proc newTexture*(engine: MyouEngine, name: string,
|
||||||
self.engine.renderer.enqueue proc()=
|
self.engine.renderer.enqueue proc()=
|
||||||
self.ensure_storage(existing_resource)
|
self.ensure_storage(existing_resource)
|
||||||
if pixels != nil:
|
if pixels != nil:
|
||||||
|
doAssert pixels.byte_len == width * height * depth * format.stride,
|
||||||
|
"Texture pixels have wrong size for the given dimensions and format"
|
||||||
self.loadFromPixelsPointer(pixels.toPointer)
|
self.loadFromPixelsPointer(pixels.toPointer)
|
||||||
else:
|
elif existing_resource == nil:
|
||||||
self.preallocate()
|
self.preallocate()
|
||||||
when defined(myouUseRenderdoc):
|
when defined(myouUseRenderdoc):
|
||||||
# Note: when we switch to arrays we'll have to store resolutions
|
# Note: when we switch to arrays we'll have to store resolutions
|
||||||
|
@ -530,7 +532,7 @@ proc newTexture*(engine: MyouEngine, name: string, file_name: string, is_sRGB: b
|
||||||
echo getCurrentExceptionMsg()
|
echo getCurrentExceptionMsg()
|
||||||
echo "Error loading texture " & file_name
|
echo "Error loading texture " & file_name
|
||||||
else:
|
else:
|
||||||
var (width, height, format) = getDimensionsFormat(res.orig_data.data, res.orig_data.byte_len, 3)
|
var (width, height, format) = getDimensionsFormat(res.orig_data.toPointer, res.orig_data.byte_len, 3)
|
||||||
if is_sRGB:
|
if is_sRGB:
|
||||||
if format in [RGB_u8, RGBA_u8]:
|
if format in [RGB_u8, RGBA_u8]:
|
||||||
format = format.to_sRGB
|
format = format.to_sRGB
|
||||||
|
|
Loading…
Reference in a new issue