From f61ae4503279e9d10824ec5512306793e1516d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Wed, 18 Apr 2018 16:34:29 -0700 Subject: [PATCH] texturec: Added *.exr output. --- include/bimg/bimg.h | 12 ++++ src/image.cpp | 124 ++++++++++++++++++++++++++++++++++++ tools/texturec/texturec.cpp | 30 ++++++++- 3 files changed, 164 insertions(+), 2 deletions(-) diff --git a/include/bimg/bimg.h b/include/bimg/bimg.h index a686f7d..8122b9e 100644 --- a/include/bimg/bimg.h +++ b/include/bimg/bimg.h @@ -470,6 +470,18 @@ namespace bimg , bx::Error* _err = NULL ); + /// + int32_t imageWriteExr( + bx::WriterI* _writer + , uint32_t _width + , uint32_t _height + , uint32_t _srcPitch + , const void* _src + , TextureFormat::Enum _format + , bool _yflip + , bx::Error* _err + ); + /// int32_t imageWriteDds( bx::WriterI* _writer diff --git a/src/image.cpp b/src/image.cpp index cafdb1b..95ae81f 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -3495,6 +3495,130 @@ namespace bimg return total; } + int32_t imageWriteExr(bx::WriterI* _writer, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, TextureFormat::Enum _format, bool _yflip, bx::Error* _err) + { + BX_ERROR_SCOPE(_err); + + switch (_format) + { + case TextureFormat::RGBA16F: + break; + + default: + BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Unsupported texture format."); + return 0; + } + + int32_t total = 0; + total += bx::write(_writer, "v/1\x01", _err); + total += bx::writeLE(_writer, uint32_t(2), _err); + + total += bx::write(_writer, "channels", _err); + total += bx::write(_writer, '\0', _err); + total += bx::write(_writer, "chlist", _err); + total += bx::write(_writer, '\0', _err); + total += bx::writeLE(_writer, uint32_t(55), _err); + + const uint8_t cdata[] = { 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 }; + total += bx::write(_writer, 'B', _err); + total += bx::write(_writer, cdata, BX_COUNTOF(cdata), _err); + total += bx::write(_writer, 'G', _err); + total += bx::write(_writer, cdata, BX_COUNTOF(cdata), _err); + total += bx::write(_writer, 'R', _err); + total += bx::write(_writer, cdata, BX_COUNTOF(cdata), _err); + total += bx::write(_writer, '\0', _err); + + total += bx::write(_writer, "compression", _err); + total += bx::write(_writer, '\0', _err); + total += bx::write(_writer, "compression", _err); + total += bx::write(_writer, '\0', _err); + total += bx::writeLE(_writer, uint32_t(1), _err); + total += bx::write(_writer, '\0', _err); // no compression + + total += bx::write(_writer, "dataWindow", _err); + total += bx::write(_writer, '\0', _err); + total += bx::write(_writer, "box2i", _err); + total += bx::write(_writer, '\0', _err); + total += bx::writeLE(_writer, uint32_t(16), _err); + total += bx::writeRep(_writer, '\0', 8, _err); + total += bx::writeLE(_writer, _width-1, _err); + total += bx::writeLE(_writer, _height-1, _err); + + total += bx::write(_writer, "displayWindow", _err); + total += bx::write(_writer, '\0', _err); + total += bx::write(_writer, "box2i", _err); + total += bx::write(_writer, '\0', _err); + total += bx::writeLE(_writer, uint32_t(16), _err); + total += bx::writeRep(_writer, '\0', 8, _err); + total += bx::writeLE(_writer, _width-1, _err); + total += bx::writeLE(_writer, _height-1, _err); + + total += bx::write(_writer, "lineOrder", _err); + total += bx::write(_writer, '\0', _err); + total += bx::write(_writer, "lineOrder", _err); + total += bx::write(_writer, '\0', _err); + total += bx::writeLE(_writer, uint32_t(1), _err); + total += bx::write(_writer, _yflip, _err); + + total += bx::write(_writer, "pixelAspectRatio", _err); + total += bx::write(_writer, '\0', _err); + total += bx::write(_writer, "float", _err); + total += bx::write(_writer, '\0', _err); + total += bx::writeLE(_writer, uint32_t(4), _err); + total += bx::writeLE(_writer, 1.0f, _err); + + total += bx::write(_writer, "screenWindowCenter", _err); + total += bx::write(_writer, '\0', _err); + total += bx::write(_writer, "v2f", _err); + total += bx::write(_writer, '\0', _err); + total += bx::writeLE(_writer, uint32_t(8), _err); + total += bx::writeRep(_writer, '\0', 8, _err); + + total += bx::write(_writer, "screenWindowWidth", _err); + total += bx::write(_writer, '\0', _err); + total += bx::write(_writer, "float", _err); + total += bx::write(_writer, '\0', _err); + total += bx::writeLE(_writer, uint32_t(4), _err); + total += bx::writeLE(_writer, 1.0f, _err); + + total += bx::write(_writer, '\0', _err); + + const uint32_t exrStride = _width*6 /* sizeof(RGB16F) */; + + uint64_t offset = 0; + for (uint32_t yy = 0; yy < _height && _err->isOk(); ++yy) + { + total += bx::writeLE(_writer, (offset), _err); + offset += exrStride + 8 /* offset */; + } + + const uint8_t* data = (const uint8_t*)_src; + for (uint32_t yy = 0; yy < _height && _err->isOk(); ++yy) + { + total += bx::writeLE(_writer, yy, _err); + total += bx::writeLE(_writer, exrStride, _err); + + for (uint32_t xx = 0; xx < _width && _err->isOk(); ++xx) + { + total += bx::write(_writer, &data[xx*8+4], 2, _err); + } + + for (uint32_t xx = 0; xx < _width && _err->isOk(); ++xx) + { + total += bx::write(_writer, &data[xx*8+2], 2, _err); + } + + for (uint32_t xx = 0; xx < _width && _err->isOk(); ++xx) + { + total += bx::write(_writer, &data[xx*8+0], 2, _err); + } + + data += _srcPitch; + } + + return total; + } + static int32_t imageWriteDdsHeader(bx::WriterI* _writer, TextureFormat::Enum _format, bool _cubeMap, uint32_t _width, uint32_t _height, uint32_t _depth, uint8_t _numMips, bx::Error* _err) { BX_ERROR_SCOPE(_err); diff --git a/tools/texturec/texturec.cpp b/tools/texturec/texturec.cpp index 19bb3c3..2f3a2e8 100644 --- a/tools/texturec/texturec.cpp +++ b/tools/texturec/texturec.cpp @@ -726,7 +726,7 @@ void help(const char* _error = NULL, bool _showHelp = true) "Supported file formats:\n" " *.bmp (input) Windows Bitmap.\n" " *.dds (input, output) Direct Draw Surface.\n" - " *.exr (input) OpenEXR.\n" + " *.exr (input, output) OpenEXR.\n" " *.gif (input) Graphics Interchange Format.\n" " *.jpg (input) JPEG Interchange Format.\n" " *.hdr (input) Radiance RGBE.\n" @@ -815,6 +815,7 @@ int main(int _argc, const char* _argv[]) saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".ktx") : saveAs; saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".dds") : saveAs; saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".png") : saveAs; + saveAs = NULL == saveAs ? bx::strFindI(outputFileName, ".exr") : saveAs; if (NULL == saveAs) { help("Output file format must be specified."); @@ -882,6 +883,18 @@ int main(int _argc, const char* _argv[]) return bx::kExitFailure; } } + else if (NULL != bx::strFindI(saveAs, "exr") ) + { + if (options.format == bimg::TextureFormat::Count) + { + options.format = bimg::TextureFormat::RGBA16F; + } + else if (options.format != bimg::TextureFormat::RGBA16F) + { + help("Ouput EXR format must be RGBA16F."); + return bx::kExitFailure; + } + } const char* quality = cmdLine.findOption('q'); if (NULL != quality) @@ -952,7 +965,20 @@ int main(int _argc, const char* _argv[]) , mip.m_height , mip.m_width*4 , mip.m_data - , bimg::TextureFormat::RGBA8 + , output->m_format + , false + , &err); + } + else if (NULL != bx::strFindI(saveAs, "exr") ) + { + bimg::ImageMip mip; + bimg::imageGetRawData(*output, 0, 0, output->m_data, output->m_size, mip); + bimg::imageWriteExr(&writer + , mip.m_width + , mip.m_height + , mip.m_width*8 + , mip.m_data + , output->m_format , false , &err); }